package xcmg.device.service.warehouse.allot;

import com.github.pagehelper.PageInfo;
import com.google.common.collect.Lists;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.CellType;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;
import org.springframework.web.client.RestTemplate;
import xcmg.device.dao.entity.DataDictionaryDO;
import xcmg.device.dao.entity.agent.ServiceBasicDataAgentDO;
import xcmg.device.dao.entity.company.CompanyInfoDO;
import xcmg.device.dao.entity.threeGuaranteesPur.ThreeReverseDO;
import xcmg.device.dao.entity.warehouse.WarehouseDO;
import xcmg.device.dao.entity.warehouse.WarehouseDeliveryDO;
import xcmg.device.dao.entity.warehouse.WarehouseDeliveryDetailDO;
import xcmg.device.dao.entity.warehouse.WarehouseInboundDO;
import xcmg.device.dao.entity.warehouse.WarehouseInboundDetailDO;
import xcmg.device.dao.entity.warehouse.allot.RegionAllotDO;
import xcmg.device.dao.entity.warehouse.allot.RegionAllotDetailDO;
import xcmg.device.dao.entity.warehouse.allot.RegionAllotExportNewDO;
import xcmg.device.dao.mapper.CompanyInfoMapper;
import xcmg.device.dao.mapper.DataDictionaryMapper;
import xcmg.device.dao.mapper.MaterialLocationRelationMapper;
import xcmg.device.dao.mapper.agent.ServiceBasicDataAgentMapper;
import xcmg.device.dao.mapper.delivery.DeliveryReceiptLinkMapper;
import xcmg.device.dao.mapper.warehouse.RegionAllotDetailMapper;
import xcmg.device.dao.mapper.warehouse.RegionAllotMapper;
import xcmg.device.dao.mapper.warehouse.WarehouseAreaLocationDOMapper;
import xcmg.device.dao.mapper.warehouse.WarehouseDOMapper;
import xcmg.device.dao.mapper.warehouse.WarehouseDeliveryDetailMapper;
import xcmg.device.dao.mapper.warehouse.WarehouseDeliveryMapper;
import xcmg.device.dao.mapper.warehouse.WarehouseInboundDetailMapper;
import xcmg.device.dao.mapper.warehouse.WarehouseInboundMapper;
import xcmg.device.dao.mapper.warehouse.WarehouseInventoryMapper;
import xcmg.device.infra.CompanyConstants;
import xcmg.device.infra.DateUtil;
import xcmg.device.infra.ErrorCode;
import xcmg.device.infra.ExportUtil;
import xcmg.device.infra.FileUtil;
import xcmg.device.infra.enums.BillDesc;
import xcmg.device.infra.enums.PurchaseStatus;
import xcmg.device.infra.enums.ReginAllotPlanStatusEnum;
import xcmg.device.service.GenDocumentService;
import xcmg.device.service.basic.MaterialsService;
import xcmg.device.service.delivery.DeliveryReceiptMaterialService;
import xcmg.device.service.threeGuaranteesPur.ThreeReverseService;
import xcmg.device.service.vo.FunctionResult;
import xcmg.device.service.vo.agent.ServiceBasicDataAgentVO;
import xcmg.device.service.vo.basic.MaterialLocationRelationVO;
import xcmg.device.service.vo.basic.MaterialsVO;
import xcmg.device.service.vo.delivery.DeliveryReceiptMaterialVO;
import xcmg.device.service.vo.delivery.ManualFinishVO;
import xcmg.device.service.vo.permission.WareHousePermission;
import xcmg.device.service.vo.threeGuaranteesPur.ThreeReverseAddVO;
import xcmg.device.service.vo.threeGuaranteesPur.ThreeReverseDetailVO;
import xcmg.device.service.vo.threeGuaranteesPur.ThreeReverseVO;
import xcmg.device.service.vo.warehouse.FindMaterialsInfos;
import xcmg.device.service.vo.warehouse.FindMaterialsNumParam;
import xcmg.device.service.vo.warehouse.WarehouseInboundAddVO;
import xcmg.device.service.vo.warehouse.WarehouseInboundDetailVO;
import xcmg.device.service.vo.warehouse.allot.RegionAllotAddVO;
import xcmg.device.service.vo.warehouse.allot.RegionAllotDetailVO;
import xcmg.device.service.vo.warehouse.allot.RegionAllotVO;
import xcmg.device.service.vo.warehouse.app.EnableAndOccupyVO;
import xcmg.device.service.vo.warehouse.sap.ObligateVO;
import xcmg.device.service.warehouse.CommonService;
import xcmg.device.service.warehouse.DepartmentWarehouseRelationService;
import xcmg.device.service.warehouse.WarehouseDeliveryService;
import xcmg.device.service.warehouse.WarehouseInboundService;
import xcmg.device.service.warehouse.WarehouseInventoryService;
import xcmg.device.service.warehouse.allot.vo.RegionAllotPlanVO;
import yb.ecp.fast.dto.UserCacheDTO;
import yb.ecp.fast.feign.AuthClient;
import yb.ecp.fast.feign.FastGenClient;
import yb.ecp.fast.infra.infra.ActionResult;
import yb.ecp.fast.infra.infra.PageCommonVO;
import yb.ecp.fast.infra.infra.SearchCommonVO;
import yb.ecp.fast.infra.util.ListUtil;
import yb.ecp.fast.infra.util.PageHelperPlus;
import yb.ecp.fast.infra.util.StringUtil;

import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class RegionAllotService {

    //区域调拨类型字典表查询键
    private static final String ALLOT_TYPE_QUERY_CODE = "ALLOT_TYPE";

    @Autowired
    private RegionAllotMapper regionAllotMapper;
    @Autowired
    private ServiceBasicDataAgentMapper serviceBasicDataAgentMapper;

    @Autowired
    private RegionAllotDetailService regionAllotDetailService;

    @Autowired
    private RegionAllotDetailMapper regionAllotDetailMapper;

    @Autowired
    private WarehouseDeliveryMapper warehouseDeliveryMapper;

    @Autowired
    private WarehouseInboundMapper warehouseInboundMapper;

    @Autowired
    private WarehouseInboundService warehouseInboundService;

    @Autowired
    private WarehouseDeliveryService warehouseDeliveryService;

    @Autowired
    private GenDocumentService genDocumentService;

    @Autowired
    private CommonService commonService;

    @Autowired
    private FastGenClient fastGenClient;

    @Autowired
    private HttpServletResponse response;

    @Autowired
    private MaterialsService materialsService;

    @Autowired
    private WarehouseInboundDetailMapper warehouseInboundDetailMapper;

    @Autowired
    private WarehouseDeliveryDetailMapper warehouseDeliveryDetailMapper;

    @Autowired
    private CompanyInfoMapper companyInfoMapper;

    @Autowired
    private MaterialLocationRelationMapper materialLocationRelationMapper;

    @Autowired
    private WarehouseDOMapper warehouseDOMapper;

    @Autowired
    private WarehouseInventoryService warehouseInventoryService;

    @Autowired
    private WarehouseInventoryMapper warehouseInventoryMapper;

    @Autowired
    private DataDictionaryMapper dataDictionaryMapper;

    @Autowired
    private DeliveryReceiptLinkMapper deliveryReceiptLinkMapper;

    @Autowired
    private DeliveryReceiptMaterialService deliveryReceiptMaterialService;
    @Autowired
    private WarehouseAreaLocationDOMapper warehouseAreaLocationDOMapper;
    @Autowired
    private AuthClient authClient;
    @Autowired
    private DepartmentWarehouseRelationService relationService;

    @Autowired
    private RegionAllotPlanService regionAllotPlanService;

    @Value("${spring.file.download.path}")
    private String filePath;

    private  String templateExcelFileName="AreaTransferImport.xls";

    @Value("${sap.area.code:0}")
    private String sapCode;

//    private static final String WJ_ORG_ID = "214678683422556160";
//
//    private static final String WJ_SAP_CODE = "9005";

    @Autowired
    private ThreeReverseService threeReverseService;

//    private static final Logger logger = LoggerFactory.getLogger(RegionAllotService.class);

//    @Autowired
//    private CompanyUtil companyUtil;

//    @Value("${sf.oms.addr}")
//    private String sfOmsApiUrl;
//
//    @Value(("${sf.oms.accessCode}"))
//    private String accessCode;
//
//    @Value("${sf.oms.checkword}")
//    private String checkWord;
//
//    @Value("${sf.oms.companyCode}")
//    private String companyCode;
//
//    @Value("${sf.oms.warehouseCode}")
//    private String warehouseCode;
//
//    @Value("${sf.oms.specialCode}")
//    private String specialCode;
//
//    @Value("${sf.oms.vendorCode}")
//    private String vendorCode;

    @Autowired
    private RestTemplate restTemplate;

    /**
     * @Author: WangKe
     * @Description: 生成区域调拨单
     * @Date: 2018/2/11 0011
     */
    @Transactional(rollbackFor = Exception.class)
    public ErrorCode add(RegionAllotAddVO regionAllotAddVO, String userId, String orgId) throws Exception {
        ActionResult<String> textResult = fastGenClient.textGuid();
        if (textResult.getCode() != ErrorCode.Success.getCode()) {
            return ErrorCode.IllegalArument;
        }
        List<RegionAllotDetailVO> detailVOList = regionAllotAddVO.getDetailList();
        if (ListUtil.isNullOrEmpty(detailVOList)) {
            return ErrorCode.MaterialsIsNull;
        }
        List<FindMaterialsInfos> infos = new ArrayList<>();
        for (RegionAllotDetailVO detailVO : detailVOList) {
            if (detailVO.getAmount() == null || detailVO.getAmount().compareTo(BigDecimal.ZERO) == 0) {
                return ErrorCode.MaterialsNumError;
            }
            FindMaterialsInfos findMaterialsInfos = new FindMaterialsInfos();
            findMaterialsInfos.setMaterialsNo(detailVO.getMaterialNo());
            findMaterialsInfos.setAmount(detailVO.getAmount());
            infos.add(findMaterialsInfos);
        }
        FindMaterialsNumParam findMaterialsNumParam = new FindMaterialsNumParam();
        findMaterialsNumParam.setMaterialsNos(infos);
        findMaterialsNumParam.setOrgId(orgId);
        findMaterialsNumParam.setWarehousCode(regionAllotAddVO.getHeaderInfo().getOutLocation());
        if (!warehouseInventoryService.findMaterialsNum(findMaterialsNumParam)) {
            return ErrorCode.PartMaterialsNotNumber;
        }
        RegionAllotVO regionAllotVO = regionAllotAddVO.getHeaderInfo();

        if (null != regionAllotVO.getInArea() && null != regionAllotVO.getOutArea()
                && regionAllotVO.getInLocation().equals(regionAllotVO.getOutLocation())
                && regionAllotVO.getInArea().equals(regionAllotVO.getOutArea())) {
            return ErrorCode.IllegalArument;
        }
        regionAllotVO.setId(textResult.getValue());
        regionAllotVO.setAllotOrder(genDocumentService.genDocumentNo(BillDesc.RegionAllot, orgId));
        regionAllotVO.setCreateId(userId);
        regionAllotVO.setCreateName(commonService.getUserName(userId));
        regionAllotVO.setOrgId(orgId);
        regionAllotVO.setInState(0);
        regionAllotVO.setOutState(0);
        regionAllotVO.setCreateDate(new Date());

        RegionAllotDO regionAllotDO = new RegionAllotDO();
        BeanUtils.copyProperties(regionAllotVO, regionAllotDO);
        regionAllotDO.setBillStatus(PurchaseStatus.WaitAudit.toString());
        DataDictionaryDO auditDataDictionaryDO = dataDictionaryMapper.itemByCode(PurchaseStatus.Name.toString(), regionAllotDO.getBillStatus());
        if (auditDataDictionaryDO != null) {
            regionAllotDO.setStatusDesc(auditDataDictionaryDO.getName());
        }
//        regionAllotDO.setAllotType(1);
        boolean success = regionAllotMapper.insert(regionAllotDO) > 0;
        if (success) {
            //生成区域调拨详情记录
            for (RegionAllotDetailVO detailVO : detailVOList) {
                detailVO.setAllotOrder(regionAllotVO.getAllotOrder());
                detailVO.setOrgId(orgId);
                detailVO.setCreateId(regionAllotVO.getCreateId());
                detailVO.setCreateName(regionAllotVO.getCreateName());

                success = regionAllotDetailService.add(detailVO);
                if (!success) {
                    throw new Exception("生成区域调拨详情记录失败");
                }
            }
        }
        updatePlanStatus4Add(regionAllotAddVO.getHeaderInfo().getAllotPlanId(), orgId);

        String type = regionAllotAddVO.getHeaderInfo().getThreeReverseType();
        if (!ObjectUtils.isEmpty(type) && "1".equals(type)) {
            updateThreeReserveOut(regionAllotAddVO, regionAllotDO.getAllotOrder());
        }
        if (!ObjectUtils.isEmpty(type) && "2".equals(type)) {
            updateThreeReserveIn(regionAllotAddVO, regionAllotDO.getAllotOrder());
        }
        return success ? ErrorCode.Success : ErrorCode.Failure;
    }

    //创建区域调拨单后，回写三包冲销-转出
    private void updateThreeReserveOut(RegionAllotAddVO regionAllotAddVO,String allotOrder) throws Exception {
        if (ObjectUtils.isEmpty(regionAllotAddVO.getHeaderInfo().getThreeReverseId())) {
            return;
        }
        ThreeReverseAddVO threeReverseAddVO = threeReverseService.findByPK(regionAllotAddVO.getHeaderInfo().getThreeReverseId());
        if (ObjectUtils.isEmpty(threeReverseAddVO) || ObjectUtils.isEmpty(threeReverseAddVO.getHeaderInfo())) {
            return;
        }
        ThreeReverseVO threeReverseVO = threeReverseAddVO.getHeaderInfo();
        List<ThreeReverseDetailVO> detailList = threeReverseAddVO.getDetailList();
        String regionAllotCodeOut = "";
        String turnOutFlag = "";
        BigDecimal amountSum = detailList.stream().map(ThreeReverseDetailVO::getRealAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
        if (ObjectUtils.isEmpty(threeReverseVO.getRegionAllotCodeOut())) {
            //BigDecimal amountSum = detailList.stream().map(ThreeReverseDetailVO::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
            BigDecimal regionAmountSum = regionAllotAddVO.getDetailList().stream().map(RegionAllotDetailVO::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
            if (regionAmountSum.compareTo(amountSum) > 0) {
                throw new Exception("调拨数量不能大于三包冲销数量,请调整");
            }
            if (regionAmountSum.compareTo(amountSum) == 0) {
                turnOutFlag = "2";
            }
            if (regionAmountSum.compareTo(amountSum) < 0) {
                turnOutFlag = "1";
            }
            regionAllotCodeOut = allotOrder;
        } else {
            List<String> allotOrderList = Arrays.asList(threeReverseVO.getRegionAllotCodeOut().split(","));
            List<RegionAllotDO> allotDOList = regionAllotMapper.findByAllotOrder(allotOrderList);
            BigDecimal regionAmountSum = regionAllotDetailService.findSumAmountByOrders(allotOrderList);
            regionAmountSum = regionAmountSum.add(regionAllotAddVO.getDetailList().stream().map(RegionAllotDetailVO::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add));
            //BigDecimal amountSum = detailList.stream().map(ThreeReverseDetailVO::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
            if (regionAmountSum.compareTo(amountSum) > 0) {
                throw new Exception("调拨数量不能大于三包冲销数量,请调整");
            }
            if (regionAmountSum.compareTo(amountSum) == 0) {
                turnOutFlag = "2";
            }
            if (regionAmountSum.compareTo(amountSum) < 0) {
                turnOutFlag = "1";
            }
            regionAllotCodeOut = threeReverseVO.getRegionAllotCodeOut() + "," + allotOrder;
        }
        ThreeReverseDO dataForUpdate = new ThreeReverseDO();
        dataForUpdate.setId(regionAllotAddVO.getHeaderInfo().getThreeReverseId());
        dataForUpdate.setRegionAllotCodeOut(regionAllotCodeOut);
        dataForUpdate.setTurnOutFlag(turnOutFlag);
        threeReverseService.updateById(dataForUpdate);
    }

    //创建区域调拨单后，回写三包冲销-转入
    private void updateThreeReserveIn(RegionAllotAddVO regionAllotAddVO,String allotOrder) throws Exception {
        if (ObjectUtils.isEmpty(regionAllotAddVO.getHeaderInfo().getThreeReverseId())) {
            return;
        }
        ThreeReverseAddVO threeReverseAddVO = threeReverseService.findByPK(regionAllotAddVO.getHeaderInfo().getThreeReverseId());
        if (ObjectUtils.isEmpty(threeReverseAddVO) || ObjectUtils.isEmpty(threeReverseAddVO.getHeaderInfo())) {
            return;
        }
        ThreeReverseVO threeReverseVO = threeReverseAddVO.getHeaderInfo();
        List<ThreeReverseDetailVO> detailList = threeReverseAddVO.getDetailList();
        String regionAllotCodeIn = "";
        String turnInFlag = "";
        BigDecimal amountSum = regionAllotDetailService.findSumAmountByOrders(Arrays.asList(threeReverseVO.getRegionAllotCodeOut().split(",")));
        if (ObjectUtils.isEmpty(threeReverseVO.getRegionAllotCodeIn())) {
            //BigDecimal amountSum = detailList.stream().map(ThreeReverseDetailVO::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
            BigDecimal regionAmountSum = regionAllotAddVO.getDetailList().stream().map(RegionAllotDetailVO::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
            if (regionAmountSum.compareTo(amountSum) > 0) {
                throw new Exception("转入数量不能大于转出数量，请调整");
            }
            if (regionAmountSum.compareTo(amountSum) == 0) {
                turnInFlag = "2";
            }
            if (regionAmountSum.compareTo(amountSum) < 0) {
                turnInFlag = "1";
            }
            regionAllotCodeIn = allotOrder;
        } else {
            List<String> allotOrderList = Arrays.asList(threeReverseVO.getRegionAllotCodeIn().split(","));
            List<RegionAllotDO> allotDOList = regionAllotMapper.findByAllotOrder(allotOrderList);
            BigDecimal regionAmountSum = regionAllotDetailService.findSumAmountByOrders(allotOrderList);
            regionAmountSum = regionAmountSum.add(regionAllotAddVO.getDetailList().stream().map(RegionAllotDetailVO::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add));
            //BigDecimal amountSum = detailList.stream().map(ThreeReverseDetailVO::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
            if (regionAmountSum.compareTo(amountSum) > 0) {
                throw new Exception("转入数量不能大于转出数量，请调整");
            }
            if (regionAmountSum.compareTo(amountSum) == 0) {
                turnInFlag = "2";
            }
            if (regionAmountSum.compareTo(amountSum) < 0) {
                turnInFlag = "1";
            }
            regionAllotCodeIn = threeReverseVO.getRegionAllotCodeIn() + "," + allotOrder;
        }

        ThreeReverseDO dataForUpdate = new ThreeReverseDO();
        dataForUpdate.setId(regionAllotAddVO.getHeaderInfo().getThreeReverseId());
        dataForUpdate.setRegionAllotCodeIn(regionAllotCodeIn);
        dataForUpdate.setTurnInFlag(turnInFlag);
        threeReverseService.updateById(dataForUpdate);
    }

    private String getRealSapCode(String orgId) {
        DataDictionaryDO dictionaryDO = dataDictionaryMapper.itemByCode(CompanyConstants.MID_WAREHOUSE_CODE, orgId);
        if (null != dictionaryDO && StringUtils.isNotBlank(dictionaryDO.getName())) {
            return dictionaryDO.getName();
        }
        return sapCode;
    }

    @Transactional(rollbackFor = Exception.class)
    public ErrorCode auditBill(RegionAllotAddVO regionAllotAddVO, String userId, String orgId) throws  Exception{
        String realSapCode = getRealSapCode(orgId);
        if(StringUtil.isNullOrEmpty(regionAllotAddVO.getHeaderInfo().getId())){
            return  ErrorCode.IllegalArument;
        }
        RegionAllotDO regionAllotDO=regionAllotMapper.selectByPrimaryKey(regionAllotAddVO.getHeaderInfo().getId());
        if(regionAllotDO==null){
            return ErrorCode.IllegalArument;
        }
        if(!regionAllotDO.getBillStatus().equals(PurchaseStatus.WaitAudit.toString())&&!regionAllotDO.getBillStatus().equals(PurchaseStatus.RefusedSumbit.toString()))
        {
            return ErrorCode.RegionAllotNotAudit;
        }
        //审核通过时，校验调拨计划数量是否超出
        if (PurchaseStatus.AuditPass.toString().equals(regionAllotAddVO.getHeaderInfo().getBillStatus())) {
            updatePlanStatus(regionAllotDO.getAllotPlanId() , orgId);
        }
        DataDictionaryDO auditDataDictionaryDO=dataDictionaryMapper.itemByCode( PurchaseStatus.Name.toString(),regionAllotAddVO.getHeaderInfo().getBillStatus());
        if(auditDataDictionaryDO!=null){
            regionAllotDO.setStatusDesc(auditDataDictionaryDO.getName());
        }
        regionAllotDO.setBillStatus(regionAllotAddVO.getHeaderInfo().getBillStatus());
        regionAllotDO.setAuditId(userId);
        regionAllotDO.setAuditDate(new Date());
        regionAllotDO.setAuditMessage(regionAllotAddVO.getHeaderInfo().getAuditMessage());
        ActionResult userAuth =  authClient.getUserDetail(userId);
        UserCacheDTO userInfo = (UserCacheDTO) userAuth.getValue();
        if(userInfo!=null){
            regionAllotDO.setAuditName(userInfo.getName());
        }
        boolean success = regionAllotMapper.updateByPrimaryKeySelective(regionAllotDO)>0;
        if(success && regionAllotDO.getBillStatus().equals(PurchaseStatus.AuditPass.toString())){
            RegionAllotAddVO allotAddVO = this.findByPK(regionAllotAddVO.getHeaderInfo().getId(), "id", orgId);
            //生成区域调拨详情记录
            List<ObligateVO> obligateVOList1 = new ArrayList<>();
            List<ObligateVO> obligateVOList2 = new ArrayList<>();
            ObligateVO obligateVO1;
            ObligateVO obligateVO2;
            for(RegionAllotDetailVO detailVO : allotAddVO.getDetailList()){
                //同步到SAP创建预留单
                obligateVO1 = new ObligateVO();
                obligateVO1.setMaterialNo(detailVO.getMaterialNo());
                obligateVO1.setAmount(detailVO.getAmount());
                obligateVO1.setMoveType(allotAddVO.getHeaderInfo().getMoveType());
                obligateVO1.setSapOutArea(allotAddVO.getHeaderInfo().getSapOutArea());
                obligateVO1.setSapInArea(realSapCode);
                obligateVOList1.add(obligateVO1);
                obligateVO2 = new ObligateVO();
                BeanUtils.copyProperties(obligateVO1, obligateVO2);
                obligateVO2.setSapOutArea(realSapCode);
                obligateVO2.setSapInArea(allotAddVO.getHeaderInfo().getSapInArea());
                obligateVOList2.add(obligateVO2);
            }

            //生成入库单
            success = warehouseInboundService.saveByRegionAllotIn(allotAddVO, userId, orgId);
            if(!success){
                throw new Exception("生成入库单时失败");
            }

            //生成出库单
            success = warehouseDeliveryService.saveByRegionAllotOut(allotAddVO, userId, orgId);
            if(!success){
                throw new Exception("生成出库单时失败");
            }

            /**
            boolean sapNoPostOrg = sapCommonService.sapNoPostOrg(orgId);
            if(!sapNoPostOrg){
                //同步到SAP创建预留单
                ObligateHeaderVO headerVO = new ObligateHeaderVO();
                headerVO.setBusinesId(allotAddVO.getHeaderInfo().getId());
                headerVO.setBusinesOrder(allotAddVO.getHeaderInfo().getAllotOrder());
                headerVO.setBusinesSingle(allotAddVO.getHeaderInfo().getAllotOrder().substring(0, 4));
                sapCommonService.createObligateOrder(headerVO, obligateVOList1, obligateVOList2 , orgId);
            }
            */

           /* //同步顺丰仓库
            SfResponseDO sfResponseDO = sendToSf(allotAddVO);
            RegionAllotDO regionAllotWriteBack = new RegionAllotDO();
            regionAllotWriteBack.setId(regionAllotDO.getId());

            //正常响应
            if (sfResponseDO.getHead().equals("OK") || sfResponseDO.getHead().equals("PART")){
                //入库成功
                if (sfResponseDO.getSfResponseBodyDO().getPurchaseOrderResponseDO().getPurchaseOrderDOList().get(0).getResult().equals("1")){
                    regionAllotWriteBack.setSyncSfFlag("0");
                    regionAllotWriteBack.setSyncSfMsg("同步顺丰成功");
                }
                //入库失败
                if (sfResponseDO.getSfResponseBodyDO().getPurchaseOrderResponseDO().getPurchaseOrderDOList().get(0).getResult().equals("2")){
                    regionAllotWriteBack.setSyncSfFlag("1");
                    String note = sfResponseDO.getSfResponseBodyDO().getPurchaseOrderResponseDO().getPurchaseOrderDOList().get(0).getNote();
                    regionAllotWriteBack.setSyncSfMsg(note);
                }
            }
            //异常响应
            if (sfResponseDO.getHead().equals("ERR")){
                regionAllotWriteBack.setSyncSfMsg("1");
                regionAllotWriteBack.setSyncSfMsg("【" + sfResponseDO.getErrorCode() + "】" + sfResponseDO.getError());
            }
            //回写同步状态
            regionAllotMapper.updateByPrimaryKeySelective(regionAllotWriteBack);*/

        }

        //审核拒绝，调用crm接口，同步crm
//        if (companyUtil.isTJ(orgId)) {  //塔机用户才同步crm
//            if (success && regionAllotDO.getBillStatus().equals(PurchaseStatus.AuditRefused.toString())) {
//                logger.info("区域调拨单审核拒绝，同步crm");
//                RegionAllotAddVO allotAddVO = this.findByPK(regionAllotAddVO.getHeaderInfo().getId(), "id", orgId);
//                syncCrm(allotAddVO);
//            }
//        }

        return success?ErrorCode.Success:ErrorCode.Failure;
    }

//    private void syncCrm(RegionAllotAddVO allotAddVO) {
//        if (ObjectUtils.isEmpty(allotAddVO))
//            return;
//        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//        List<RegionAllotCrmDO> regionAllotCrmDOList = new ArrayList<>();
//        String pmsCode = "";
//        Integer allotType = allotAddVO.getHeaderInfo().getAllotType();
//        String crmOrder = allotAddVO.getHeaderInfo().getCrmOrder();
//
//        //allotType=1并且crmOrder不为空，pmsCode取allotPlanOrder
//        if (!ObjectUtils.isEmpty(allotType) && allotType.equals(1) && !ObjectUtils.isEmpty(crmOrder)) {
//            pmsCode = allotAddVO.getHeaderInfo().getAllotPlanOrder();
//        }
//
//        //allotType=2，pmsCode取allotOrder
//        if (!ObjectUtils.isEmpty(allotType) && allotType.equals(2)) {
//            pmsCode = allotAddVO.getHeaderInfo().getAllotOrder();
//        }
//
//        for (RegionAllotDetailVO regionAllotDetailVO : allotAddVO.getDetailList()) {
//            RegionAllotCrmDO regionAllotCrmDO = new RegionAllotCrmDO();
//            regionAllotCrmDO.setCode(regionAllotDetailVO.getMaterialNo());
//            regionAllotCrmDO.setPmsCode(pmsCode);
//            regionAllotCrmDO.setReceiveQty(regionAllotDetailVO.getAmount().toString());
//            regionAllotCrmDO.setReceiveTime(sdf.format(new Date()));
//            regionAllotCrmDO.setStatus(ConstantInfo.CRM_STATUS_CANCLE);
//            regionAllotCrmDOList.add(regionAllotCrmDO);
//        }
//        Map<String, List<RegionAllotCrmDO>> paramMap = new HashMap<>();
//
//
//        //allotType=1并且crmOrder不为空,调用发货签收接口
//        if (!ObjectUtils.isEmpty(allotType) && allotType.equals(1) && !ObjectUtils.isEmpty(crmOrder)) {
//            paramMap.put("DeliveryReceiptlist", regionAllotCrmDOList);
//            logger.info("同步crm发货签收,请求入参{}", JsonUtil.objectToString(paramMap));
//            Map resultMap = crmClient.syncPartsApply(paramMap);
//            logger.info("同步crm发货签收,返回结果{}", JsonUtil.objectToString(resultMap));
//        }
//
//        //allotType=2,调用前移备件申请发货和签收信息接口
//        if (!ObjectUtils.isEmpty(allotType) && allotType.equals(2)) {
//            paramMap.put("list", regionAllotCrmDOList);
//            logger.info("同步crm前移备件申请发货和签收信息,请求入参{}", JsonUtil.objectToString(paramMap));
//            Map resultMap = crmClient.syncForwardPartsApply(paramMap);
//            logger.info("同步crm前移备件申请发货和签收信息,返回结果{}", JsonUtil.objectToString(resultMap));
//        }
//    }

    /**
     * @Author: WangKe
     * @Description: 更新区域调拨记录
     * @Date: 2018/2/11 0011
     */
    @Transactional(rollbackFor = Exception.class)
    public ErrorCode update(RegionAllotAddVO regionAllotAddVO, String orgId) throws Exception
    {
        RegionAllotVO allotVO = regionAllotAddVO.getHeaderInfo();
        List<RegionAllotDetailVO> detailVOList = regionAllotAddVO.getDetailList();
        List<RegionAllotDetailVO> newDetailVOList = new ArrayList<>();
        if (allotVO == null || StringUtil.isNullOrEmpty(allotVO.getAllotOrder()))
        {
            return ErrorCode.IllegalArument;
        }
        //bug-view-13693.html 可更新:调出仓库，调出库区，调入仓库，收货人，收货人联系方式，收货地址
        updateRegionAllotDO(allotVO);

        if (ListUtil.isNullOrEmpty(detailVOList))
        {
            return ErrorCode.MaterialsIsNull;
        }
        List<FindMaterialsInfos> infos=new ArrayList<>();
        for (RegionAllotDetailVO detailVO : detailVOList)
        {
            if(detailVO.getOutAmount() == null || detailVO.getInAmount() == null){
                continue;
            }
            if (detailVO.getOutState() == 2 && detailVO.getAmount().compareTo(detailVO.getOutAmount()) != 0)
            {
                return ErrorCode.RegionAllotDeleteDisable;
            }
            if (detailVO.getAmount().compareTo(detailVO.getOutAmount()) < 0)
            {
                return ErrorCode.RegionAllotAmountError;
            }
            if (detailVO.getInState() == 2 && detailVO.getAmount().compareTo(detailVO.getOutAmount()) != 0)
            {
                throw new Exception("入库已完成，不允许修改调拨数量");
            }
            if (detailVO.getAmount().compareTo(detailVO.getInAmount()) < 0)
            {
                throw new Exception("调拨数量不能小于已出库数量");
            }
            if(detailVO.getOutState()<=1){
                FindMaterialsInfos findMaterialsInfos=new FindMaterialsInfos();
                findMaterialsInfos.setMaterialsNo(detailVO.getMaterialNo());
                findMaterialsInfos.setAmount(detailVO.getAmount().subtract(detailVO.getOutAmount()));
                infos.add(findMaterialsInfos);
            }
        }
        FindMaterialsNumParam findMaterialsNumParam=new FindMaterialsNumParam();
        findMaterialsNumParam.setMaterialsNos(infos);
        findMaterialsNumParam.setOrgId(orgId);
        findMaterialsNumParam.setBusinessOrder(regionAllotAddVO.getHeaderInfo().getAllotOrder());
        findMaterialsNumParam.setWarehousCode(regionAllotAddVO.getHeaderInfo().getOutLocation());
        if(!warehouseInventoryService.findMaterialsNum(findMaterialsNumParam)){
            return ErrorCode.PartMaterialsNotNumber;
        }
        RegionAllotDO sourceRegionAlloDO=regionAllotMapper.selectByPrimaryKey(allotVO.getId());
        if(sourceRegionAlloDO==null)
        {
            return ErrorCode.Failure;
        }
        if(sourceRegionAlloDO.getBillStatus().equals(PurchaseStatus.AuditPass.toString())){
            return  ErrorCode.IllegalArument;
        }

        //删除未出库的零件
        regionAllotDetailMapper.deleteNotComplete(allotVO.getAllotOrder(), orgId);
        //warehouseInboundDetailMapper.deleteNotComplete(allotVO.getAllotOrder(), orgId);
        warehouseDeliveryDetailMapper.deleteNotComplete(allotVO.getAllotOrder(), orgId);

        RegionAllotDetailVO vo = new RegionAllotDetailVO();
        vo.setAllotOrder(allotVO.getAllotOrder());
        vo.setOrgId(orgId);
        boolean success;
        boolean allComplete = true;
        boolean someComplete = false;
        List<RegionAllotDetailDO> detailDOList = regionAllotDetailMapper.list(vo);

        //判断是否删除了部分出库或者已出库的零件
        if(!ListUtil.isNullOrEmpty(detailDOList)){
            int num = 0;
            for(RegionAllotDetailDO detail : detailDOList){
                for(RegionAllotDetailVO newDetail : detailVOList){
                    if(detail.getId().equals(newDetail.getId())){
                        num++;
                    }
                }
            }
            if(detailDOList.size() != num){
                throw new Exception("只能删除未调出的零件");
            }
        }

        if(!ListUtil.isNullOrEmpty(detailDOList)){
            for(RegionAllotDetailDO detail : detailDOList){
                for(RegionAllotDetailVO newDetail : detailVOList){
                    if(detail.getId().equals(newDetail.getId())){
                        if(newDetail.getAmount().compareTo(detail.getAmount()) != 0){
                            detail.setAmount(newDetail.getAmount());
                            if(detail.getAmount().compareTo(detail.getOutAmount()) == 0){
                                detail.setOutState(2);
                            }else{
                                if(detail.getOutAmount().compareTo(BigDecimal.ZERO) == 0){
                                    detail.setOutState(0);
                                }else{
                                    detail.setOutState(1);
                                }
                            }
                            if(detail.getAmount().compareTo(detail.getOutAmount()) == 0){
                                detail.setInState(2);
                            }else{
                                if(detail.getOutAmount().compareTo(BigDecimal.ZERO) == 0){
                                    detail.setInState(0);
                                }else{
                                    detail.setInState(1);
                                }
                            }
                            success = regionAllotDetailMapper.updateByPrimaryKeySelective(detail)>0;
                            if(!success){
                                throw new Exception("更新失败");
                            }

                            //更新出库事物单详情记录
                            ErrorCode errorCode = warehouseDeliveryService.updateDetailState(detail.getAllotOrder(), detail.getMaterialNo(), detail.getAmount(), detail.getOutState(), orgId);
                            if (errorCode.getCode() != 0)
                            {
                                throw new Exception("更新出库事物单详情记录失败");
                            }

                            //更新入库事物单详情记录失败
                            errorCode = warehouseInboundService.updateDetailState(detail.getAllotOrder(), detail.getMaterialNo(), detail.getAmount(), detail.getInState(), orgId);
                            if (errorCode.getCode() != 0)
                            {
                                throw new Exception("更新入库事物单详情记录失败");
                            }
                        }

                    }else{
                        if(newDetail.getOutState() == 0 && !newDetailVOList.contains(newDetail)){
                            newDetailVOList.add(newDetail);
                        }

                    }
                }
            }
        }else{
            newDetailVOList.addAll(detailVOList);
        }

        if(!ListUtil.isNullOrEmpty(newDetailVOList)){
            for(RegionAllotDetailVO detailVO : newDetailVOList){
                detailVO.setAllotOrder(allotVO.getAllotOrder());
                detailVO.setOrgId(orgId);
                detailVO.setCreateId(allotVO.getCreateId());
                detailVO.setCreateName(allotVO.getCreateName());

                success = regionAllotDetailService.add(detailVO);
                if(!success){
                    throw new Exception("新增区域调拨详情记录失败");
                }

                insetInboundDetail(allotVO, detailVO);
            }
        }


        int outState = regionAllotDetailMapper.findOutState(allotVO.getAllotOrder(), orgId);

        RegionAllotDO regionAllotDO = new RegionAllotDO();
        regionAllotDO.setId(allotVO.getId());
        regionAllotDO.setOutState(outState);
        regionAllotDO.setBillStatus(PurchaseStatus.WaitAudit.toString());
        if(sourceRegionAlloDO.getBillStatus().equals(PurchaseStatus.AuditRefused.toString())){
            regionAllotDO.setBillStatus(PurchaseStatus.RefusedSumbit.toString());
        }
        DataDictionaryDO auditDataDictionaryDO=dataDictionaryMapper.itemByCode( PurchaseStatus.Name.toString(),regionAllotDO.getBillStatus());
        if(auditDataDictionaryDO!=null){
            regionAllotDO.setStatusDesc(auditDataDictionaryDO.getName());
        }
        success = regionAllotMapper.updateByPrimaryKeySelective(regionAllotDO) > 0;
        if (!success)
        {
            throw new Exception("更新区域调拨单主记录失败");
        }
        //更新出库事务单
        ErrorCode errorCode = ErrorCode.Success;
        if(allotVO.getBillStatus().equals(PurchaseStatus.AuditPass.toString())){
            errorCode = warehouseDeliveryService.updateState(allotVO.getAllotOrder(), allotVO.getOutState(), orgId);
            if (errorCode.getCode() != 0)
            {
                throw new Exception("更新出库事务单失败");
            }
            errorCode = warehouseInboundService.updateState(allotVO.getAllotOrder(), allotVO.getOutState(), orgId);
            if (errorCode.getCode() != 0)
            {
                throw new Exception("更新入库事务单失败");
            }

            errorCode = reflashPriceAndAmount(regionAllotAddVO.getHeaderInfo().getAllotOrder(),orgId);
        }
        updatePlanStatus(sourceRegionAlloDO.getAllotPlanId(), orgId);
        return errorCode;
    }
    //bug-view-13693.html 可更新:调出仓库，调出库区，调入仓库，收货人，收货人联系方式，收货地址
    private void updateRegionAllotDO(RegionAllotVO allotVO) {
        RegionAllotDO regionAllotDO = new RegionAllotDO();
        regionAllotDO.setId(allotVO.getId());
        //调出仓库，调出库区，调入仓库，收货人，收货人联系方式，收货地址
        regionAllotDO.setOutLocation(allotVO.getOutLocation());
        regionAllotDO.setOutArea(allotVO.getOutArea());
        regionAllotDO.setInLocation(allotVO.getInLocation());
        regionAllotDO.setInArea(allotVO.getInArea());
        regionAllotDO.setReceiveUser(allotVO.getReceiveUser());
        regionAllotDO.setReceiveTel(allotVO.getReceiveTel());
        regionAllotDO.setReceiveAddress(allotVO.getReceiveAddress());
        boolean success = regionAllotMapper.updateByPrimaryKeySelective(regionAllotDO) > 0;
        if(!success){
            throw new RuntimeException("更新调拨单表头失败");
        }
    }

    /**
     * 创建调拨单后回写调拨计划的状态
     *
     * @param allotPlanId
     * @param orgId
     * @throws Exception
     */
    private void updatePlanStatus4Add(String allotPlanId, String orgId) throws Exception {
        if (StringUtils.isEmpty(allotPlanId)) {
            return;
        }
        RegionAllotPlanVO planVO = regionAllotPlanService.queryById(allotPlanId, orgId);
        if (null == planVO) {
            throw new Exception("未查询到调拨计划");
        }
        if (!ReginAllotPlanStatusEnum.canCreateRegionAllot(planVO.getPlanStatus())) {
            throw new Exception("当前状态的调拨计划不能创建区域调拨单");
        }
        regionAllotPlanService.updatePlanstatus(allotPlanId, orgId);
    }

    /**
     * 修改、删除、审核调拨单后回写调拨计划的状态
     *
     * @param allotPlanId
     * @param orgId
     * @throws Exception
     */
    private void updatePlanStatus(String allotPlanId, String orgId) throws Exception {
        if (StringUtils.isEmpty(allotPlanId)) {
            return;
        }
        regionAllotPlanService.updatePlanstatus(allotPlanId, orgId);
    }

    @Transactional(rollbackFor = Exception.class)
    public ErrorCode adjust(RegionAllotAddVO regionAllotAddVO, String orgId) throws Exception {
        RegionAllotVO allotVO = regionAllotAddVO.getHeaderInfo();
        List<RegionAllotDetailVO> detailVOList = regionAllotAddVO.getDetailList();
        if (allotVO == null || StringUtil.isNullOrEmpty(allotVO.getAllotOrder())) {
            return ErrorCode.IllegalArument;
        }
        if (ListUtil.isNullOrEmpty(detailVOList)) {
            return ErrorCode.MaterialsIsNull;
        }
        boolean success;
        List<FindMaterialsInfos> infos=new ArrayList<>();
        for (RegionAllotDetailVO detailVO : detailVOList)
        {
            if(detailVO.getOutState()<=1){
                FindMaterialsInfos findMaterialsInfos=new FindMaterialsInfos();
                findMaterialsInfos.setMaterialsNo(detailVO.getMaterialNo());
                findMaterialsInfos.setAmount(detailVO.getAmount().subtract(detailVO.getOutAmount()));
                infos.add(findMaterialsInfos);
            }
        }
        FindMaterialsNumParam findMaterialsNumParam=new FindMaterialsNumParam();
        findMaterialsNumParam.setMaterialsNos(infos);
        findMaterialsNumParam.setOrgId(orgId);
        findMaterialsNumParam.setBusinessOrder(regionAllotAddVO.getHeaderInfo().getAllotOrder());
        findMaterialsNumParam.setWarehousCode(regionAllotAddVO.getHeaderInfo().getOutLocation());
        if(!warehouseInventoryService.findMaterialsNum(findMaterialsNumParam)){
            return ErrorCode.PartMaterialsNotNumber;
        }
        List<String> idsList = new ArrayList<>();
        List<RegionAllotDetailVO> updateList = new ArrayList<>();
        for (RegionAllotDetailVO detailVO : detailVOList) {
            idsList.add(detailVO.getId());
            if (detailVO.getOutAmount() == null || detailVO.getInAmount() == null || detailVO.getOutState() == 2) {
                continue;
            }
//            if (detailVO.getAmount().compareTo(detailVO.getOldAmount()) == 0) {
//                continue;
//            }
            if (detailVO.getAmount().compareTo(detailVO.getOldAmount()) > 0) {
                throw new Exception("调整后数量不能大于原数量");
            }
            if (detailVO.getAmount().compareTo(detailVO.getOutAmount()) < 0) {
                return ErrorCode.RegionAllotAmountError;
            }
            updateList.add(detailVO);
        }
        List<RegionAllotDetailDO> removeList = regionAllotDetailMapper.listForRemove(allotVO.getAllotOrder(), orgId, idsList);

        //更新零件
        List<String> receiptIds = deliveryReceiptLinkMapper.findReceiptIds(allotVO.getId());
        List<DeliveryReceiptMaterialVO> receiptMaterialVOList = new ArrayList<>();

        if (!ListUtil.isNullOrEmpty(updateList)) {
            RegionAllotDetailDO record = new RegionAllotDetailDO();
            for (RegionAllotDetailVO detailVO : updateList) {
                int outState = 0;
                if(detailVO.getOutAmount().compareTo(BigDecimal.ZERO) > 0){
                    outState = detailVO.getAmount().compareTo(detailVO.getOutAmount()) == 0 ? 2 : 1;
                }

                record.setId(detailVO.getId());
                record.setOutState(outState);
                record.setAmount(detailVO.getAmount());
                record.setRemark(detailVO.getRemark());
                success = regionAllotDetailMapper.updateByPrimaryKeySelective(record) > 0;
                if (!success) {
                    throw new Exception("更新零件状态失败");
                }

                //更新出库事物单详情记录
                warehouseDeliveryService.updateDetailState(detailVO.getAllotOrder(), detailVO.getMaterialNo(), detailVO.getAmount(), outState, orgId);

                //更新入库事物单详情记录失败
                warehouseInboundService.updateDetailState(detailVO.getAllotOrder(), detailVO.getMaterialNo(), detailVO.getAmount(), detailVO.getInState(), orgId);

                for (String receiptId : receiptIds) {
                    DeliveryReceiptMaterialVO receiptMaterialVO = new DeliveryReceiptMaterialVO();
                    receiptMaterialVO.setMaterialsNo(detailVO.getMaterialNo());
                    receiptMaterialVO.setOldQty(detailVO.getOldAmount());
                    receiptMaterialVO.setQty(detailVO.getAmount());
                    receiptMaterialVO.setDeliveryReceiptId(receiptId);
                    receiptMaterialVO.setUpdateType(1);
                    receiptMaterialVOList.add(receiptMaterialVO);
                }
            }
        }

        if (!ListUtil.isNullOrEmpty(removeList)) {
            for (RegionAllotDetailDO detailDO : removeList) {
                regionAllotDetailMapper.deleteByPrimaryKey(detailDO.getId());

                //删除出入库事物详情
                warehouseDeliveryDetailMapper.remove(detailDO.getAllotOrder(), orgId, detailDO.getMaterialNo());
                WarehouseInboundDetailDO record = new WarehouseInboundDetailDO();
                record.setBusinessOrder(detailDO.getAllotOrder());
                record.setOrgId(orgId);
                record.setMaterialNo(detailDO.getMaterialNo());
                warehouseInboundDetailMapper.deleteByMaterial(record);

                for (String receiptId : receiptIds) {
                    DeliveryReceiptMaterialVO receiptMaterialVO = new DeliveryReceiptMaterialVO();
                    receiptMaterialVO.setMaterialsNo(detailDO.getMaterialNo());
                    receiptMaterialVO.setQty(detailDO.getAmount());
                    receiptMaterialVO.setDeliveryReceiptId(receiptId);
                    receiptMaterialVO.setUpdateType(0);
                    receiptMaterialVOList.add(receiptMaterialVO);
                }
            }
        }

        int outState = regionAllotDetailMapper.findOutState(allotVO.getAllotOrder(), orgId);
        RegionAllotDO regionAllotDO = new RegionAllotDO();
        regionAllotDO.setId(allotVO.getId());
        regionAllotDO.setOutState(outState);
        success = regionAllotMapper.updateByPrimaryKeySelective(regionAllotDO) > 0;
        if (!success) {
            throw new Exception("更新区域调拨单主记录失败");
        }
        //更新出库事务单
        ErrorCode errorCode;
        if (allotVO.getBillStatus().equals(PurchaseStatus.AuditPass.toString())) {
            errorCode = warehouseDeliveryService.updateState(allotVO.getAllotOrder(), outState, orgId);
            if (errorCode.getCode() != 0) {
                throw new Exception("更新出库事务单失败");
            }

            reflashPriceAndAmount(regionAllotAddVO.getHeaderInfo().getAllotOrder(), orgId);
        }

        //更新发运交接单
        deliveryReceiptMaterialService.updateByAdjust(receiptIds, receiptMaterialVOList);

        RegionAllotDO regionAllotDB = regionAllotMapper.selectByPrimaryKey(allotVO.getId());
        updatePlanStatus(regionAllotDB.getAllotPlanId(), orgId);
        return ErrorCode.Success;
    }


    private int getOrderStatus(int unFinishCount, int finishCount, int childQty) {
        int orderOutState;

        //未完成数量
        if (unFinishCount == childQty) {
            orderOutState = 0;
        } else if (finishCount == childQty) {
            orderOutState = 2;
        } else {
            orderOutState = 1;
        }
        return orderOutState;
    }


    private void insetInboundDetail(RegionAllotVO allotVO, RegionAllotDetailVO detailVO)throws Exception{
        boolean success;
        WarehouseInboundDO inboundDO = warehouseInboundMapper.selectByOrder(allotVO.getAllotOrder(), allotVO.getOrgId());
        if(inboundDO == null){
            return;
        }
        WarehouseInboundDetailDO inboundDetailDO = new WarehouseInboundDetailDO();
        BeanUtils.copyProperties(inboundDO, inboundDetailDO);
        inboundDetailDO.setId(fastGenClient.textGuid().getValue());
        inboundDetailDO.setMaterialNo(detailVO.getMaterialNo());
        inboundDetailDO.setMaterialName(detailVO.getMaterialName());
        inboundDetailDO.setMaterialType(detailVO.getMaterialType());
        inboundDetailDO.setUnit(detailVO.getUnit());
        inboundDetailDO.setAmount(detailVO.getAmount());
        inboundDetailDO.setRealAmount(BigDecimal.ZERO);
        inboundDetailDO.setPrintNum(BigDecimal.ZERO);
        inboundDetailDO.setPrintState(0);
        inboundDetailDO.setStatus(0);
        inboundDetailDO.setNote("");
        inboundDetailDO.setCreateDate(new Date());
        success = warehouseInboundDetailMapper.insert(inboundDetailDO)>0;
        if(!success){
            throw new Exception("更新失败");
        }

        WarehouseDeliveryDO deliveryDO = warehouseDeliveryMapper.findByBusinessOrder(allotVO.getAllotOrder(), allotVO.getOrgId());
        if(deliveryDO == null){
            return;
        }
        WarehouseDeliveryDetailDO deliveryDetailDO = new WarehouseDeliveryDetailDO();
        BeanUtils.copyProperties(deliveryDO, deliveryDetailDO);
        deliveryDetailDO.setId(fastGenClient.textGuid().getValue());
        deliveryDetailDO.setMaterialNo(detailVO.getMaterialNo());
        deliveryDetailDO.setMaterialName(detailVO.getMaterialName());
        deliveryDetailDO.setMaterialType(detailVO.getMaterialType());
        deliveryDetailDO.setUnit(detailVO.getUnit());
        deliveryDetailDO.setAmount(detailVO.getAmount());
        deliveryDetailDO.setRealAmount(BigDecimal.ZERO);
        deliveryDetailDO.setStatus(0);
        deliveryDetailDO.setNote("");
        deliveryDetailDO.setCreateDate(new Date());
        success = warehouseDeliveryDetailMapper.insert(deliveryDetailDO)>0;
        if(!success){
            throw new Exception("更新失败");
        }

    }

    /**
     * 获取区域调拨单中被删除的零件，并删除
     * <br>根据参数集合paramList和数据库中的源数据sourceList比较，sourceList中多余的数据将被删除
     * @param regionAllotAddVO RegionAllotAddVO
     * @param orgId String
     * @return List<RegionAllotDetailVO>
     */
    private ErrorCode deleteSomthing(RegionAllotAddVO regionAllotAddVO, String orgId)
    {
        List<RegionAllotDetailVO> resultList = new ArrayList<>();
        List<RegionAllotDetailVO> paramList = regionAllotAddVO.getDetailList();
        RegionAllotDetailVO detailVO = new RegionAllotDetailVO();
        detailVO.setAllotOrder(regionAllotAddVO.getHeaderInfo().getAllotOrder());
        detailVO.setOrgId(orgId);
        List<RegionAllotDetailDO> sourceList = regionAllotDetailMapper.list(detailVO);

        for (RegionAllotDetailDO source : sourceList)
        {
            boolean flag = false;  //当值没有变为true，标识该条记录为被删除状态
            for (RegionAllotDetailVO temp : paramList)
            {
                if (StringUtil.isNullOrEmpty(temp.getId()))
                {
                    continue;
                }
                if (source.getId().equals(temp.getId()))
                {
                    flag = true;
                }
            }

            if (!flag)
            {
                //删除
                ErrorCode errorCode = deleteDetail(source.getId(), source.getAllotOrder(), source.getMaterialNo(), orgId);
                if (errorCode != ErrorCode.Success)
                {
                    return errorCode;
                }
            }
        }
        return ErrorCode.Success;
    }

    /**
     * 删除零件操作
     * <br>删除盘点单零件信息，以及删除入库事务单和出库事务单零件信息
     * @param detailId String
     * @param billNo String
     * @param materialNo String
     * @param orgId String
     * @return ErrorCode
     */
    private ErrorCode deleteDetail(String detailId, String billNo, String materialNo, String orgId)
    {
        WarehouseDeliveryDetailDO detailDO  = new WarehouseDeliveryDetailDO();
        detailDO.setMaterialNo(materialNo);
        detailDO.setOrgId(orgId);
        detailDO.setBusinessOrder(billNo);
        ErrorCode errorCode = warehouseDeliveryService.deleteByMaterial(detailDO);

        if(errorCode!= ErrorCode.Success)
        {
            return errorCode;
        }

        WarehouseInboundDetailDO inboundDetailDO = new WarehouseInboundDetailDO();
        inboundDetailDO.setMaterialNo(materialNo);
        inboundDetailDO.setOrgId(orgId);
        inboundDetailDO.setBusinessOrder(billNo);
        errorCode = warehouseInboundService.deleteByMaterial(inboundDetailDO);

        if(errorCode!= ErrorCode.Success)
        {
            return errorCode;
        }
        regionAllotDetailMapper.deleteByPrimaryKey(detailId);
        return errorCode;
    }

    /**
     * 更新入库事物单的入库总数量和价格，并更新出库单的总数量
     * @param billNo String
     * @param orgId String
     * @return ErrorCode
     */
    private ErrorCode reflashPriceAndAmount(String billNo, String orgId)
    {
        ErrorCode errorCode = warehouseInboundService.refreshAmountAndPrice(billNo, orgId);
        if (errorCode != ErrorCode.Success)
        {
            return errorCode;
        }
        errorCode = warehouseDeliveryService.refreshAmount(billNo, orgId);

        return errorCode;
    }

    /**
     * @Author: WangKe
     * @Description: 删除区域调拨记录，连同详情记录
     * @Date: 2018/2/11 0011
     */
    @Transactional
    public ErrorCode remove(List<String> ids, String orgId) throws Exception {
        List<RegionAllotDO> list = regionAllotMapper.findForDeleteByIds(ids);
        List<RegionAllotDO> regionAllotDOList = regionAllotMapper.findByIds(ids);
        if(!ListUtil.isNullOrEmpty(list)){
            return ErrorCode.RegionAllotDeleteError;
        }
        List<String> planIdList = listAllotPlanId(ids);
        List<String> orderList = regionAllotMapper.findOrderList(ids);

        //区域调拨单删除，调用crm接口
//        if (companyUtil.isTJ(orgId)) {  //塔机用户才同步crm
//            for (String id : ids) {
//                logger.info("区域调拨单删除，同步crm");
//                RegionAllotAddVO allotAddVO = this.findByPK(id, "id", orgId);
//                syncCrm(allotAddVO);
//            }
//        }

        boolean success = regionAllotMapper.remove(ids)>0;
        //删除区域调拨详情记录
        if(success && CollectionUtils.isNotEmpty(orderList)) {
            regionAllotDetailMapper.removeByAllotOrderList(orderList, orgId);
//            //删除事物单
//            warehouseDeliveryService.removeByBusinessOrders(orderList, orgId);
//            warehouseInboundService.removeByBusinessOrders(orderList, orgId);
            // 删除后回写调拨计划的状态与数量
            if (CollectionUtils.isNotEmpty(planIdList)) {
                for (String planId : planIdList) {
                    updatePlanStatus(planId, orgId);
                }
            }
        }
        removeThreeReverseCode(regionAllotDOList);

        return success? ErrorCode.Success: ErrorCode.Failure;
    }

    private void removeThreeReverseCode(List<RegionAllotDO> regionAllotDOList){
        List<String> threeReverseIds = Lists.newArrayList();
        for (RegionAllotDO regionAllotDO : regionAllotDOList) {
            if (!ObjectUtils.isEmpty(regionAllotDO.getThreeReverseId())) {
                threeReverseIds.add(regionAllotDO.getThreeReverseId());
            }
        }
        if (ObjectUtils.isEmpty(threeReverseIds)) {
            return;
        }
        Map<String, ThreeReverseDO> threeReverseDOMap = threeReverseService.findBatchByIds(threeReverseIds).stream().collect(Collectors.toMap(ThreeReverseDO::getId, a -> a, (k1, k2) -> k1));

        List<ThreeReverseDO> listForUpdate = Lists.newArrayList();
        for (RegionAllotDO regionAllotDO : regionAllotDOList) {
            if (ObjectUtils.isEmpty(regionAllotDO.getThreeReverseType())) {
                continue;
            }

            if (threeReverseDOMap.containsKey(regionAllotDO.getThreeReverseId())) {
                ThreeReverseDO threeReverseDO = threeReverseDOMap.get(regionAllotDO.getThreeReverseId());

                //转入
                if ("2".equals(regionAllotDO.getThreeReverseType())) {
                    String regionAllotCodeIn = threeReverseDO.getRegionAllotCodeIn();
                    if (ObjectUtils.isEmpty(regionAllotCodeIn)) {
                        continue;
                    }
                    List<String> allotOrderList =new ArrayList<>(Arrays.asList(regionAllotCodeIn.split(",")));
                    allotOrderList.remove(regionAllotDO.getAllotOrder());
                    regionAllotCodeIn = StringUtils.join(allotOrderList, ",");
                    threeReverseDO.setRegionAllotCodeIn(regionAllotCodeIn);
                    if(ObjectUtils.isEmpty(regionAllotCodeIn)) {
                        threeReverseDO.setTurnInFlag("0");
                    } else {
                        threeReverseDO.setTurnInFlag("1");
                    }
                }

                //转出
                if ("1".equals(regionAllotDO.getThreeReverseType())) {
                    String regionAllotCodeOut = threeReverseDO.getRegionAllotCodeOut();
                    if (ObjectUtils.isEmpty(regionAllotCodeOut)) {
                        continue;
                    }
                    List<String> allotOrderList = new ArrayList<>(Arrays.asList(regionAllotCodeOut.split(",")));
                    allotOrderList.remove(regionAllotDO.getAllotOrder());
                    regionAllotCodeOut = StringUtils.join(allotOrderList, ",");
                    threeReverseDO.setRegionAllotCodeOut(regionAllotCodeOut);
                    if (ObjectUtils.isEmpty(regionAllotCodeOut)) {
                        threeReverseDO.setTurnOutFlag("0");
                    } else {
                        threeReverseDO.setTurnOutFlag("1");
                    }
                }
                listForUpdate.add(threeReverseDO);
            }
        }

        threeReverseService.batchUpdateById(listForUpdate);

    }

    private List<String> listAllotPlanId(List<String> ids) {
        List<String> allotPlanIds = new ArrayList<>();
        for (String regionAllotId : ids) {
            RegionAllotDO regionAllotDO = regionAllotMapper.selectByPrimaryKey(regionAllotId);
            if (null == regionAllotDO || StringUtils.isBlank(regionAllotDO.getAllotPlanId())) {
                continue;
            }
            allotPlanIds.add(regionAllotDO.getAllotPlanId());
        }
        return allotPlanIds;
    }

    /**
     * @Author: WangKe
     * @Description: 获取区域调拨单列表
     * @Date: 2018/2/11 0011
     */
    public PageCommonVO list(SearchCommonVO<RegionAllotVO> condition,String deptId){

        PageCommonVO<RegionAllotVO> result = new PageCommonVO();
        // 判断当前登陆的用户所属组织机构是否有配置仓库，如果开启了仓库控制并配置了仓库，则需要把配置的仓库加入到查询的限制条件
        WareHousePermission wareHousePermission = relationService.hasMajorWareHousePermission(condition.getFilters().getOrgId(), deptId);
        if (!wareHousePermission.isHasPermission()) {
            result.setPageInfo(new PageInfo(new ArrayList()));
            result.setPageInfoList(new ArrayList<>());
            return result;
        } else {
            condition.getFilters().setWarehousePermitList(wareHousePermission.getPermissionWarehouses());
        }
        PageHelperPlus.orderBy("create_date desc");
        PageHelperPlus.startPage(condition.getPageNum(), condition.getPageSize());
        List<RegionAllotDO> doList = regionAllotMapper.list(condition.getFilters());
        List<RegionAllotVO> voList = new ArrayList<RegionAllotVO>();
        for (RegionAllotDO entity : doList) {
            RegionAllotVO model = new RegionAllotVO();
            BeanUtils.copyProperties(entity, model);
            voList.add(model);
        }
        result.setPageInfo(new PageInfo(doList));
        result.setPageInfoList(voList);
        return result;
    }

    /**
     * @Author: WangKe
     * @Description: 根据主键或者调拨单号获取实体和详情
     * @Date: 2018/2/11 0011
     */
    public RegionAllotAddVO findByPK(String id, String type, String orgId){
        RegionAllotAddVO model = new RegionAllotAddVO();
        RegionAllotDO entity;
        if("id".equals(type)){
            entity = regionAllotMapper.selectByPrimaryKey(id);
        }else{
            entity = regionAllotMapper.selectByAllotOrder(id, orgId);
        }
        if(entity == null){
            return null;
        }

        List<RegionAllotDetailDO> doList = regionAllotDetailMapper.listByBillNo(entity.getAllotOrder(), orgId);
        List<RegionAllotDetailVO> voList = new ArrayList<RegionAllotDetailVO>();
        MaterialLocationRelationVO relationVO = new MaterialLocationRelationVO();
        MaterialLocationRelationVO inRelationVO = new MaterialLocationRelationVO();
        EnableAndOccupyVO enableAndOccupyVO;
        if(CollectionUtils.isNotEmpty(doList)){
            RegionAllotDetailVO regionAllotDetailVO;
            for(RegionAllotDetailDO detailDO:doList){
                regionAllotDetailVO = new RegionAllotDetailVO();
                BeanUtils.copyProperties(detailDO, regionAllotDetailVO);

                relationVO.setOrgId(entity.getOrgId());
                relationVO.setMaterialNo(detailDO.getMaterialNo());
                relationVO.setWarehouseCode(entity.getOutLocation());
                relationVO.setAreaCode(entity.getOutArea());
                List<String> locationCodeList = warehouseInventoryMapper.findLocationCode(orgId, detailDO.getMaterialNo(), entity.getOutLocation(), entity.getOutArea());
                if (!locationCodeList.isEmpty()) {
                    regionAllotDetailVO.setLocationCode(String.join(",", locationCodeList));
                    List<String> locationDescList = new ArrayList<>();
                    for (String locationCode : locationCodeList) {
                        String locationDesc = warehouseAreaLocationDOMapper.getLocationDesc(locationCode);
                        locationDescList.add(locationDesc);
                    }
                    regionAllotDetailVO.setLocationDesc(String.join(",", locationDescList));

                }

                regionAllotDetailVO.setStockLocation(materialLocationRelationMapper.findLocationCode(relationVO));
//                if (StringUtils.isNotBlank(regionAllotDetailVO.getLocationCode())){
//                    regionAllotDetailVO.setLocationDesc(warehouseAreaLocationDOMapper.getLocationDesc(regionAllotDetailVO.getLocationCode()));
//                }

                inRelationVO.setOrgId(entity.getOrgId());
                inRelationVO.setMaterialNo(detailDO.getMaterialNo());
                inRelationVO.setWarehouseCode(entity.getInLocation());
                inRelationVO.setAreaCode(entity.getInArea());
                regionAllotDetailVO.setInLocationCode(materialLocationRelationMapper.findLocationCode(inRelationVO));
                if (StringUtils.isNotBlank(regionAllotDetailVO.getInLocationCode())){
                    regionAllotDetailVO.setInLocationDesc(warehouseAreaLocationDOMapper.getLocationDesc(regionAllotDetailVO.getInLocationCode()));
                }

                enableAndOccupyVO = warehouseInventoryService.findEnableAndOccupyNum(detailDO.getMaterialNo(), entity.getOrgId(), entity.getOutLocation());
                BeanUtils.copyProperties(enableAndOccupyVO, regionAllotDetailVO);
                regionAllotDetailVO.setOldAmount(regionAllotDetailVO.getAmount());
                voList.add(regionAllotDetailVO);
            }
        }
        RegionAllotVO regionAllotVO = new RegionAllotVO();
        BeanUtils.copyProperties(entity, regionAllotVO);

        if (StringUtils.isNotBlank(regionAllotVO.getInLocation())) {
            WarehouseDO warehouse = warehouseDOMapper.itemByWarehouseCode(orgId, regionAllotVO.getInLocation());
            if (null != warehouse) {
                regionAllotVO.setInWarehouseCodeDesc(warehouse.getDescription());
            }
        }
        if (StringUtils.isNotBlank(regionAllotVO.getOutLocation())) {
            WarehouseDO warehouse = warehouseDOMapper.itemByWarehouseCode(orgId, regionAllotVO.getOutLocation());
            if (null != warehouse) {
                regionAllotVO.setOutWarehouseCodeDesc(warehouse.getDescription());
            }
        }
        itemRegionAllotAssembleAllotTypeDesc(regionAllotVO);//拼接区域调拨类型
        model.setHeaderInfo(regionAllotVO);
        Collections.sort(voList, new Comparator<RegionAllotDetailVO>() {
            @Override
            public int compare(RegionAllotDetailVO o1, RegionAllotDetailVO o2) {
                if (o1.getLocationCode()==null && o2.getLocationCode()==null){
                    return 0;
                }else if (o1.getLocationCode()==null){
                    return -1;
                }else if (o2.getLocationCode()==null){
                    return 1;
                }else {
                    return o1.getLocationCode().compareTo(o2.getLocationCode());
                }
            }
        });
        model.setDetailList(voList);
        return model;
    }

    /**
     * @Des 区域调拨查看详情时拼接区域调拨类型的中文描述
     * @Date 2021/6/1 11:42
     * @Author wangzhaoyu
     * @Param [regionAllotVO]
     * @Return void
     */
    private void itemRegionAllotAssembleAllotTypeDesc(RegionAllotVO regionAllotVO){
        if(regionAllotVO == null){
            return ;
        }
        Integer allotType = regionAllotVO.getAllotType();
        if(allotType == null){
            return ;
        }
        String orgId = regionAllotVO.getOrgId();
        ServiceBasicDataAgentVO queryCondition = new ServiceBasicDataAgentVO();
        queryCondition.setOrgId(orgId);
        queryCondition.setpCode(ALLOT_TYPE_QUERY_CODE);
        List<ServiceBasicDataAgentDO> qyeryResult = serviceBasicDataAgentMapper.queryList(queryCondition);
        if(CollectionUtils.isEmpty(qyeryResult)){
            return ;
        }
        for(ServiceBasicDataAgentDO dataAgent : qyeryResult){
            String code = dataAgent.getCode();
            if(allotType.toString().equals(code)){
                String name = dataAgent.getName();
                regionAllotVO.setAllotTypeDesc(name);
                break;
            }
        }
    }

    /**
     * @Author: WangKe
     * @Description: 导出区域调拨单记录
     * @Date: 2018/2/11 0011
     */
    public void export(List<String> ids)throws Exception{
        invokeExport(regionAllotMapper.findByIds(ids));
    }

    /**
     * @Author: WangKe
     * @Description: 导出全部区域调拨单记录
     * @Date: 2018/2/11 0011
     */
    public void exportAll(RegionAllotVO condition)throws Exception {
//        Integer count = regionAllotMapper.findCountForExportAll(condition);
//        List<RegionAllotExportNewDO> dataList = new ArrayList<>();
//        int times = count/500+1;
//        for(int i=0; i<times; i++){
        //PageHelperPlus.startPage(0, 0, "create_date desc");
        List<RegionAllotExportNewDO> dataList = regionAllotMapper.selectExportList(condition);
        //dataList.addAll(regionAllotMapper.selectExportList(condition));
        //}
        invokeExportNew(dataList);
    }

    /**
     * @Author: WangKe
     * @Description: 导出区域调拨单记录
     * @Date: 2018/2/11 0011
     */
    private void invokeExport(List<RegionAllotDO> doList)throws Exception{
        String title = "区域调拨单数据导出";
        String[] rowsName = new String[]{"序号","调拨单号","调度员","移出仓库","领出零件凭证",
                "单据状态","调出状态", "移入仓库", "领入零件凭证", "调入状态",
                "移动类型","制单时间","制单部门","制单人","SAP领出预留号","SAP领入预留号","CRM单号",
                "零件编码","零件名称","单位","申请数量","调出完成数","调入完成数", "储位", "保管员"};
        List<Object[]>  dataList = new ArrayList<Object[]>();
        List<RegionAllotDetailDO> list;
        Object[] objs;
        for (int i = 0; i < doList.size(); i++) {
            RegionAllotDO exportDO = doList.get(i);
            list = regionAllotDetailMapper.findByAllotOrderListForLocationUser(Arrays.asList(exportDO.getAllotOrder()), exportDO.getOrgId());
            for(RegionAllotDetailDO detailDO : list){
                objs = new Object[rowsName.length];
                objs[0] = i+1;
                objs[1] = exportDO.getAllotOrder();
                objs[2] = exportDO.getDispatcherName();
                objs[3] = exportDO.getOutLocation();
                objs[4] = exportDO.getVoucherOutNo();
                objs[5] = exportDO.getStatusDesc();
                objs[6] = getState(exportDO.getOutState());
                objs[7] = exportDO.getInLocation();
                objs[8] = exportDO.getVoucherInNo();
                objs[9] = getState(exportDO.getInState());
                objs[10] = exportDO.getMoveType();
                objs[11] = DateUtil.formatDateTime(exportDO.getCreateDate());
                objs[12] = exportDO.getDeptName();
                objs[13] = exportDO.getCreateName();
                objs[14] = exportDO.getSapOutOrder();
                objs[15] = exportDO.getSapInOrder();
                objs[16] = exportDO.getCrmOrder();
                objs[17] = detailDO.getMaterialNo();
                objs[18] = detailDO.getMaterialName();
                objs[19] = detailDO.getUnit();
                objs[20] = detailDO.getAmount();
                objs[21] = detailDO.getOutAmount();
                objs[22] = detailDO.getInAmount();
                objs[23] = detailDO.getStockLocation();
                objs[24] = detailDO.getStockUserName();
                dataList.add(objs);
            }
        }
        ExportUtil exportUtil = new ExportUtil(title, rowsName, dataList);
        exportUtil.export(response);
    }


    private void invokeExportNew(List<RegionAllotExportNewDO> doList)throws Exception{
        String title = "区域调拨单数据导出";
        String[] rowsName = new String[]{"序号","调拨单号","调度员","移出仓库","领出零件凭证",
                "单据状态","调出状态", "移入仓库", "领入零件凭证", "调入状态",
                "移动类型","制单时间","制单部门","制单人","SAP领出预留号","SAP领入预留号","CRM单号",
                "零件编码","零件名称","单位","申请数量","调出完成数","调入完成数", "储位", "保管员"};
        List<Object[]>  dataList = new ArrayList<Object[]>();
        Object[] objs;
        for (int i = 0; i < doList.size(); i++) {
            RegionAllotExportNewDO exportDO = doList.get(i);
            //list = regionAllotDetailMapper.findByAllotOrderListForLocationUser(Arrays.asList(exportDO.getAllotOrder()), exportDO.getOrgId());
            objs = new Object[rowsName.length];
            objs[0] = i+1;
            objs[1] = exportDO.getAllotOrder();
            objs[2] = exportDO.getDispatcherName();
            objs[3] = exportDO.getOutLocation();
            objs[4] = exportDO.getVoucherOutNo();
            objs[5] = exportDO.getStatusDesc();
            objs[6] = getState(exportDO.getOutState());
            objs[7] = exportDO.getInLocation();
            objs[8] = exportDO.getVoucherInNo();
            objs[9] = getState(exportDO.getInState());
            objs[10] = exportDO.getMoveType();
            objs[11] = DateUtil.formatDateTime(exportDO.getCreateDate());
            objs[12] = exportDO.getDeptName();
            objs[13] = exportDO.getCreateName();
            objs[14] = exportDO.getSapOutOrder();
            objs[15] = exportDO.getSapInOrder();
            objs[16] = exportDO.getCrmOrder();
            objs[17] = exportDO.getMaterialNo();
            objs[18] = exportDO.getMaterialName();
            objs[19] = exportDO.getUnit();
            objs[20] = exportDO.getAmount();
            objs[21] = exportDO.getOutAmount();
            objs[22] = exportDO.getInAmount();
            objs[23] = exportDO.getStockLocation();
            objs[24] = exportDO.getStockUserName();
            dataList.add(objs);
        }
        ExportUtil exportUtil = new ExportUtil(title, rowsName, dataList);
        exportUtil.export(response);
    }

    private String getState(Integer state){
        if(state == null){
            state = 0;
        }
        if(state == 0 ){
            return "未完成";
        }else if(state == 1 ){
            return "部分完成";
        }else if(state == 2){
            return "已完成";
        }else{
            return "强制完成";
        }
    }

    /**
     * @Author: WangKe
     * @Description: 零件批量导入
     * @Date: 2018/3/1 0001
     */
    public FunctionResult importExcel(InputStream in, String warehouseCode, String areaCode, String orgId) throws Exception{
        FunctionResult result=new FunctionResult();
        HSSFWorkbook wb=new HSSFWorkbook(in);
        HSSFSheet sheet=wb.getSheetAt(0);

        int totalRow=sheet.getLastRowNum();
        if(totalRow<2){
            result.setCode(ErrorCode.IllegalArument);
            result.setValue("导入模板不正确");
            return result;
        }
        int totalCell=sheet.getRow(1).getLastCellNum();
        if(totalCell!=5){
            result.setCode(ErrorCode.IllegalArument);
            result.setValue("导入模板不正确");
            return result;
        }
        List<RegionAllotDetailVO> detailVOList=new ArrayList<>();
        List<RegionAllotDetailVO> errorDetailVOList=new ArrayList<>();
        MaterialLocationRelationVO relationVO = new MaterialLocationRelationVO();
        EnableAndOccupyVO enableAndOccupyVO;
        for (int i=2;i<=totalRow;i++){
            HSSFRow curRow=sheet.getRow(i);
            RegionAllotDetailVO detailVO=new RegionAllotDetailVO();
            if(curRow==null){
                continue;
            }
            String no = getCellValue(curRow, 0);
            String materialsNo = getCellValue(curRow, 1);
            String qty = getCellValue(curRow, 4);
            if(StringUtil.isNullOrEmpty(no) && StringUtil.isNullOrEmpty(materialsNo) && StringUtil.isNullOrEmpty(qty)){
                continue;
            }
            if(StringUtil.isNullOrEmpty(no)){
                detailVO.setErrorRow(i+1);
                detailVO.setRemark("序号不能为空");
                errorDetailVOList.add(detailVO);
                continue;
            }
            if(StringUtil.isNullOrEmpty(materialsNo)){
                detailVO.setErrorRow(i+1);
                detailVO.setRemark("零件编码不能为空");
                errorDetailVOList.add(detailVO);
                continue;
            }
            if(StringUtil.isNullOrEmpty(qty)){
                detailVO.setErrorRow(i+1);
                detailVO.setRemark("申请数量不能为空");
                errorDetailVOList.add(detailVO);
                continue;
            }
            if(!isInteger(qty) || "0".equals(qty)){
                detailVO.setErrorRow(i+1);
                detailVO.setRemark("申请数量格式不正确");
                errorDetailVOList.add(detailVO);
                continue;
            }
            if(new BigDecimal(qty).compareTo(BigDecimal.valueOf(99999999.99)) > 0){
                detailVO.setErrorRow(i+1);
                detailVO.setRemark("申请数量过大");
                errorDetailVOList.add(detailVO);
                continue;
            }
            MaterialsVO materialsVO=materialsService.itemByNo(materialsNo, orgId);
            if(materialsVO==null){
                detailVO.setErrorRow(i+1);
                detailVO.setRemark("零件不存在");
                errorDetailVOList.add(detailVO);
                continue;
            }
            detailVO.setAmount(new BigDecimal(qty));
            detailVO.setMaterialNo(materialsVO.getMaterialsNo());
            detailVO.setMaterialName(materialsVO.getMaterialsDes());
            detailVO.setMaterialType(materialsVO.getMaterialsType());
            detailVO.setUnit(materialsVO.getUnit());

            relationVO.setOrgId(orgId);
            relationVO.setMaterialNo(materialsVO.getMaterialsNo());
            relationVO.setWarehouseCode(warehouseCode);
            relationVO.setAreaCode(areaCode);
            detailVO.setLocationCode(materialLocationRelationMapper.findLocationCode(relationVO));
            enableAndOccupyVO = warehouseInventoryService.findEnableAndOccupyNum(detailVO.getMaterialNo(), orgId, warehouseCode);
            BeanUtils.copyProperties(enableAndOccupyVO, detailVO);
            detailVOList.add(detailVO);
        }

        if(ListUtil.isNullOrEmpty(errorDetailVOList)){
            result.setValue(deRepeat(detailVOList));
            result.setCode(ErrorCode.Success);
        }else{
            result.setValue(errorDetailVOList);
            result.setCode(ErrorCode.IllegalArument);
        }
        return result;
    }

    private boolean isInteger(String str) {
        if (null == str || "".equals(str)) {
            return false;
        }
        try {
            BigDecimal decimal = new BigDecimal(str);
        }catch (Exception e){
            return false;
        }
        return true;
    }

    private String getCellValue(HSSFRow curRow, int i){
        String value = "";
        if(curRow.getCell(i) != null){
            curRow.getCell(i).setCellType(CellType.STRING);
            value = curRow.getCell(i).getStringCellValue();
        }
        return value;
    }

    public static List<RegionAllotDetailVO> deRepeat(List<RegionAllotDetailVO> repeatList) {
        if(CollectionUtils.isEmpty(repeatList)){
            return repeatList;
        }
        for  ( int i  = 0 ; i< repeatList.size()-1;i++){
            BigDecimal sum =repeatList.get(i).getAmount();
            for  ( int j=repeatList.size()-1;j>i;j -- )  {
                if  (repeatList.get(j).equals(repeatList.get(i))||repeatList.get(j).getMaterialNo().equals(repeatList.get(i).getMaterialNo())){
                    sum=sum.add(repeatList.get(j).getAmount());
                    repeatList.remove(j);
                }
            }
            repeatList.get(i).setAmount(sum);
        }
        return repeatList;
    }

    /**
     * @Author: WangKe
     * @Description: 下载零件批量导入模板
     * @Date: 2018/3/1 0001
     */
    public void download() throws Exception{
        FileUtil.downLoadFile(response, filePath, templateExcelFileName);
    }


    /**
     * 手动完成单据<br>
     *     materialsNo 不为null,则更改该单据下的零件状态为“手动完成”状态；如果materialsNo为空，则更改整个单据为“手动完成”状态
     * @param billNo  String 单据编号
     * @param materialsNo String 零件编号
     * @param orgId String 企业ID
     * @param type 操作类型（0入库操作，1出库操作）
     * @return ErrorCode 返回码
     */
    public ErrorCode manualFinish(String billNo,String materialsNo,String orgId,int type)
    {
        if (StringUtil.isNullOrEmpty(materialsNo))//零件编码为空，更新单据状态为“手动完成”
        {
            if (0 == type)//入库操作
            {
                regionAllotMapper.updateInStatus(3, billNo);
                warehouseInboundService.updateState(billNo, 3, orgId);
            }
            else  //出库操作
            {
                regionAllotMapper.updateOutStatus(3, billNo);
                warehouseDeliveryService.updateState(billNo, 3, orgId);
            }
        }
        else
        {
            if (0 == type)//入库操作
            {
                regionAllotDetailMapper.updateInStatus(3, billNo, materialsNo);
                warehouseInboundService.updateDetailState(billNo, materialsNo, null, 3, orgId);
                ErrorCode errorCode = checkBillFinished(billNo, orgId,type);

                if (ErrorCode.Success != errorCode)
                {
                    return errorCode;
                }
            }
            else
            {
                regionAllotDetailMapper.updateOutStatus(3, billNo, materialsNo);
                warehouseDeliveryService.updateDetailState(billNo, materialsNo, null, 3, orgId);
                ErrorCode errorCode = checkBillFinished(billNo, orgId,type);

                if (ErrorCode.Success != errorCode)
                {
                    return errorCode;
                }
            }
        }
        return ErrorCode.Success;
    }

    /**
     * @Des 出库结单
     * @Date 2020/12/24 15:38
     * @Author wangzhaoyu
     * @Param [manualFinishVO, orgId]
     * @Return xcmg.device.infra.ErrorCode
     */
    @Transactional
    public ErrorCode manualFinishOut(ManualFinishVO manualFinishVO, String orgId) {
        //审核通过未完成出库时候允许结单
        RegionAllotDO h = regionAllotMapper.selectByAllotOrder(manualFinishVO.getBillNo(), orgId);
        //校验合法性并返回调拨单行记录
        Map<String, RegionAllotDetailDO> detailDOMap = checkReturnDetailMap(h);
        //出库事务单
        WarehouseDeliveryDO warehouseDeliveryDO = warehouseDeliveryMapper.findByBusinessOrder(manualFinishVO.getBillNo(), orgId);
        if (warehouseDeliveryDO == null) {
            throw new RuntimeException("WarehouseDeliveryDO查询失败");
        }
        List<WarehouseDeliveryDetailDO> warehouseDeliveryDetailDOS = warehouseDeliveryDetailMapper.findByBusinessOrder(manualFinishVO.getBillNo(), orgId);
        if (ListUtil.isNullOrEmpty(warehouseDeliveryDetailDOS)) {
            throw new RuntimeException("WarehouseDeliveryDetailDO查询失败");
        }
        WarehouseInboundAddVO inboundAddVO = warehouseInboundService.findByPK(manualFinishVO.getBillNo(), "order" , orgId);
        if(null==inboundAddVO||null==inboundAddVO.getHeaderInfo()|| org.apache.commons.collections4.CollectionUtils.isEmpty(inboundAddVO.getDetailList())){
            throw new RuntimeException("warehouseInboundService查询失败");
        }
        //所以行记录出库数量都是0
        boolean allLineAmountIs0 = true;
        int endBillStatus = 3;

        RegionAllotDO crmSyncUpdateDO = new RegionAllotDO();
        crmSyncUpdateDO.setAllotOrder(h.getAllotOrder());
        crmSyncUpdateDO.setId(h.getId());
        crmSyncUpdateDO.setAllotType(h.getAllotType());
        crmSyncUpdateDO.setAllotPlanOrder(h.getAllotPlanOrder());
        crmSyncUpdateDO.setCrmOrder(h.getCrmOrder());

        if (StringUtils.isBlank(manualFinishVO.getMaterialsNo())) {
            //整单结单
            updateRegionAllotOutState(h.getId(), endBillStatus);
            //更新出库事务单
            updateWarehouseDeliverStatus(warehouseDeliveryDO.getId(), endBillStatus);


            for (Map.Entry<String, RegionAllotDetailDO> en : detailDOMap.entrySet()) {
                if (en.getValue().getOutAmount().compareTo(BigDecimal.ZERO) > 0) {
                    allLineAmountIs0 = false;
                }
                updateRegionAllotDetailOutState(en.getValue().getId(), endBillStatus);
                //出库事务单结单(更新其状态)
                updateWarehouseDeliveryDetailStatus(warehouseDeliveryDetailDOS, en.getValue().getMaterialNo(), en.getValue().getOutAmount(), endBillStatus, inboundAddVO.getDetailList());

                //调用crm接口，同步crm状态
//                if (companyUtil.isTJ(orgId) && en.getValue().getOutAmount().compareTo(BigDecimal.ZERO) <= 0) {  //塔机用户才同步crm,并且出库数量为0
//                    Map resultMap = regionAllotDetailService.syncCrmBymanualFinishOut(crmSyncUpdateDO.getAllotOrder(), en.getValue().getMaterialNo(), crmSyncUpdateDO);
//
//                    boolean isSuccess = true;
//                    //syncCrmFlag为null，为未同步
//                    if (!xcmg.device.infra.StringUtil.isNotEmpty(crmSyncUpdateDO.getSyncCrmFlag())){
//                        crmSyncUpdateDO.setSyncCrmFlag("0");
//                    }
//                    //同步失败需要回写
//                    if (resultMap.get("Flag") != null && resultMap.get("Flag").equals(false)) {
//                        String msg = crmSyncUpdateDO.getSyncCrmMsg() == null ? "" : crmSyncUpdateDO.getSyncCrmMsg();
//                        msg += resultMap.get("Msg").toString() + ";";
//                        crmSyncUpdateDO.setSyncCrmFlag("2");
//                        crmSyncUpdateDO.setSyncCrmMsg(msg);
//                        isSuccess = false;
//                    }
//
//                    //本次成功，并且之前没有失败记录，则回写成功
//                    if (isSuccess && !crmSyncUpdateDO.getSyncCrmFlag().equals("2")){
//                        crmSyncUpdateDO.setSyncCrmFlag("1");
//                        crmSyncUpdateDO.setSyncCrmMsg("操作成功");
//                    }
//                }
            }
            regionAllotMapper.updateByPrimaryKeySelective(crmSyncUpdateDO);

        } else {
            //单行记录结单
            RegionAllotDetailDO detailDO = detailDOMap.get(manualFinishVO.getMaterialsNo());
            if (null == detailDO) {
                throw new RuntimeException("零件编码错误");
            }
            detailDO.setOutState(endBillStatus);
            //调拨单行记录结单
            updateRegionAllotDetailOutState(detailDO.getId(), endBillStatus);

            //出库事务单结单(更新其状态)
            updateWarehouseDeliveryDetailStatus(warehouseDeliveryDetailDOS, detailDO.getMaterialNo(), detailDO.getOutAmount(), endBillStatus, inboundAddVO.getDetailList());
            //计算总单据的状态
            boolean headEndFlag = true;
            for (Map.Entry<String, RegionAllotDetailDO> en : detailDOMap.entrySet()) {
                if (2 == en.getValue().getOutState().intValue() || 3 == en.getValue().getOutState().intValue()) {
                    if (en.getValue().getOutAmount().compareTo(BigDecimal.ZERO) > 0) {
                        allLineAmountIs0 = false;
                    }
                    continue;
                } else {
                    allLineAmountIs0 = false;
                    headEndFlag = false;
                    break;
                }
            }
            if (headEndFlag) {
                updateRegionAllotOutState(h.getId(), endBillStatus);
                updateWarehouseDeliverStatus(warehouseDeliveryDO.getId(), endBillStatus);
            }

//            //调用crm接口，同步crm状态
//            if (companyUtil.isTJ(orgId) && detailDO.getOutAmount().compareTo(BigDecimal.ZERO) <= 0) {  //塔机用户才同步crm,并且出库数量为0
//                Map resultMap = regionAllotDetailService.syncCrmBymanualFinishOut(crmSyncUpdateDO.getAllotOrder(), manualFinishVO.getMaterialsNo(), crmSyncUpdateDO);
//
//                //同步失败需要回写
//                if (resultMap.get("Flag") != null && resultMap.get("Flag").equals(false)) {
//                    String msg = resultMap.get("Msg").toString();
//                    crmSyncUpdateDO.setSyncCrmFlag("2");
//                    crmSyncUpdateDO.setSyncCrmMsg(msg);
//                } else {
//                    crmSyncUpdateDO.setSyncCrmFlag("1");
//                    crmSyncUpdateDO.setSyncCrmMsg("操作成功");
//                }
//            }
            regionAllotMapper.updateByPrimaryKeySelective(crmSyncUpdateDO);
        }
        if (allLineAmountIs0) {
            //出库单上数量都为0，入库单状态，也设置为结单
            WarehouseInboundDO inboundDO = new WarehouseInboundDO();
            inboundDO.setId(inboundAddVO.getHeaderInfo().getId());
            inboundDO.setStatus(endBillStatus);
            warehouseInboundMapper.updateByPrimaryKeySelective(inboundDO);

        }
        return ErrorCode.Success;
    }

    /**
     * 更新出库事务单行记录状态
     * @param materialNo
     * @param outAmount
     * @param endBillStatus
     */
    private void updateWarehouseDeliveryDetailStatus(List<WarehouseDeliveryDetailDO> warehouseDeliveryDetailDOS, String materialNo, BigDecimal outAmount, int endBillStatus, List<WarehouseInboundDetailVO> indList) {
        Map<String, WarehouseDeliveryDetailDO> dmap = warehouseDeliveryDetailDOS.parallelStream().collect(Collectors.toMap(WarehouseDeliveryDetailDO::getMaterialNo, a -> a, (k1, k2) -> k1));
        Map<String, WarehouseInboundDetailVO> inMap = indList.parallelStream().collect(Collectors.toMap(WarehouseInboundDetailVO::getMaterialNo, a -> a, (k1, k2) -> k1));
        WarehouseDeliveryDetailDO d = dmap.get(materialNo);
        if (null == d) {
            throw new RuntimeException("查询出库事务单行记录失败");
        }
        WarehouseInboundDetailVO inboundDetailVO = inMap.get(materialNo);
        if (null == inboundDetailVO) {
            throw new RuntimeException("查询入库事务单行记录失败");
        }
        WarehouseDeliveryDetailDO inboundDetailDO = new WarehouseDeliveryDetailDO();
        inboundDetailDO.setId(d.getId());
        inboundDetailDO.setAmount(outAmount);
        inboundDetailDO.setStatus(endBillStatus);
        warehouseDeliveryDetailMapper.updateByPrimaryKey(inboundDetailDO);
        WarehouseInboundDetailDO inD = new WarehouseInboundDetailDO();
        inD.setId(inboundDetailVO.getId());
        inD.setAmount(outAmount);
        if (outAmount.compareTo(BigDecimal.ZERO) == 0) {
            inD.setStatus(2);
        }
        warehouseInboundDetailMapper.updateByPrimaryKeySelective(inD);
    }


    /**
     * 更新调拨单行记录出库状态
     * @param id
     * @param endBillStatus
     */
    private void updateRegionAllotDetailOutState(String id, int endBillStatus) {
        RegionAllotDetailDO dm=new RegionAllotDetailDO();
        dm.setId(id);
        dm.setOutState(endBillStatus);
        regionAllotDetailMapper.updateByPrimaryKeySelective(dm);
    }

    private Map<String, RegionAllotDetailDO> checkReturnDetailMap(RegionAllotDO h) {
        if (null == h) {
            throw new RuntimeException("参数错误");
        }
        List<RegionAllotDetailDO> doList = regionAllotDetailMapper.listByBillNo(h.getAllotOrder(), h.getOrgId());
        if (org.apache.commons.collections4.CollectionUtils.isEmpty(doList)) {
            throw new RuntimeException("参数错误");
        }
        Map<String, RegionAllotDetailDO> detailDOMap = doList.parallelStream().collect(Collectors.toMap(RegionAllotDetailDO::getMaterialNo, a -> a, (k1, k2) -> k1));
        //审核通过，且未出库完成
        if (!"2".equals(h.getBillStatus())) {
            throw new RuntimeException("审核状态非审核通过");
        }
        if (!(0 == h.getOutState().intValue() || 1 == h.getOutState())) {
            throw new RuntimeException("只有未完全出库的调拨单可以结单");
        }
        return detailDOMap;
    }


    /**
     * 更新出库状态
     * @param id
     * @param endBillStatus
     */
    private void updateRegionAllotOutState(String id, int endBillStatus) {
        RegionAllotDO m=new RegionAllotDO();
        m.setId(id);
        m.setOutState(endBillStatus);
        regionAllotMapper.updateByPrimaryKeySelective(m);
    }

    /**
     * 更新出库基表状态
     * @param id
     * @param endBillStatus
     */
    private void updateWarehouseDeliverStatus(String id, int endBillStatus) {
        WarehouseDeliveryDO upModel=new WarehouseDeliveryDO();
        upModel.setId(id);
        upModel.setStatus(endBillStatus);
        warehouseDeliveryMapper.updateByPrimaryKey(upModel);
    }


    /**
     * 校验单据是否已完成<br>
     *     判断单据下的所有零件是否已经完成，如果都完成，则更改单据状态为完成
     * @param billNo String
     * @param orgId String
     * @param type 操作类型（0入库操作，1出库操作）
     * @return Boolean
     */
    private ErrorCode checkBillFinished(String billNo,String orgId,int type)
    {
        boolean flag = true;
        List<RegionAllotDetailDO> detailDOs = regionAllotDetailMapper.listByBillNo(billNo, orgId);

        if (0 == type)
        {
            for (RegionAllotDetailDO temp : detailDOs)
            {
                if (2==temp.getInState() || 3==temp.getInState())
                {
                    //完成状态
                    continue;
                }
                flag = false;
            }
            if (flag)
            {
                regionAllotMapper.updateInStatus(3, billNo);
                warehouseInboundService.updateState(billNo, 3, orgId);
            }
        }
        else
        {
            for (RegionAllotDetailDO temp : detailDOs)
            {
                if (2==temp.getOutState() || 3==temp.getOutState())
                {
                    //完成状态
                    continue;
                }
                flag = false;
            }
            if (flag)
            {
                regionAllotMapper.updateOutStatus(3, billNo);
                warehouseDeliveryService.updateState(billNo, 3, orgId);
            }
        }

        return ErrorCode.Success;
    }

    private ActionResult getResult(ErrorCode errorCode, String value) {
        return new ActionResult(errorCode.getCode(), errorCode.getDesc(), value);
    }

    /**
     * 添加区域调拨单（对外接口）
     *
     * @param regionAllotAddVO
     * @return
     * @throws Exception
     */
    @Transactional(rollbackFor = Exception.class)
    public ActionResult addRegionAllot(RegionAllotAddVO regionAllotAddVO) throws Exception {
        ActionResult<String> textResult = fastGenClient.textGuid();
        if (textResult.getCode() != ErrorCode.Success.getCode()) {
            return getResult(ErrorCode.IllegalArument, "获取GUID出错");
        }
        List<RegionAllotDetailVO> detailVOList = regionAllotAddVO.getDetailList();
        if (ListUtil.isNullOrEmpty(detailVOList)) {
            return getResult(ErrorCode.Failure, "缺少明细数据");
        }
        for (RegionAllotDetailVO detailVO : detailVOList) {
            if (detailVO.getAmount() == null || detailVO.getAmount().compareTo(BigDecimal.ZERO) == 0) {
                return getResult(ErrorCode.Failure, "数量不能为0");
            }
        }
        RegionAllotVO regionAllotVO = regionAllotAddVO.getHeaderInfo();
        CompanyInfoDO companyInfoDO = companyInfoMapper.itemBySap(regionAllotAddVO.getHeaderInfo().getSapCode());
        if (null == companyInfoDO) {
            return getResult(ErrorCode.Failure, "sapCode错误");
        }
        String orgId = companyInfoDO.getOrgId();
        String userId = regionAllotVO.getCreateId();
        regionAllotVO.setId(textResult.getValue());
        regionAllotVO.setAllotOrder(genDocumentService.genDocumentNo(BillDesc.RegionAllot, orgId));
        regionAllotVO.setOrgId(orgId);
        regionAllotVO.setInState(0);
        regionAllotVO.setOutState(0);
        regionAllotVO.setCreateDate(new Date());

        RegionAllotDO regionAllotDO = new RegionAllotDO();
        BeanUtils.copyProperties(regionAllotVO, regionAllotDO);

        String realSapCode = getRealSapCode(orgId);

        if (regionAllotMapper.insert(regionAllotDO) > 0) {
            //生成区域调拨详情记录
            List<ObligateVO> obligateVOList1 = new ArrayList<>();
            List<ObligateVO> obligateVOList2 = new ArrayList<>();
            ObligateVO obligateVO1;
            ObligateVO obligateVO2;
            for (RegionAllotDetailVO detailVO : detailVOList) {
                detailVO.setAllotOrder(regionAllotVO.getAllotOrder());
                detailVO.setOrgId(orgId);
                detailVO.setCreateId(regionAllotVO.getCreateId());
                detailVO.setCreateName(regionAllotVO.getCreateName());
                detailVO.setInAmount(BigDecimal.ZERO);
                detailVO.setInState(0);
                detailVO.setOutAmount(BigDecimal.ZERO);
                detailVO.setOutState(0);
                if (!regionAllotDetailService.add(detailVO)) {
                    throw new Exception("生成区域调拨详情记录失败");
                }

                //同步到SAP创建预留单
                obligateVO1 = new ObligateVO();
                obligateVO1.setMaterialNo(detailVO.getMaterialNo());
                obligateVO1.setAmount(detailVO.getAmount());
                obligateVO1.setMoveType(regionAllotVO.getMoveType());
                obligateVO1.setSapOutArea(regionAllotVO.getSapOutArea());
                obligateVO1.setSapInArea(realSapCode);
                obligateVOList1.add(obligateVO1);
                obligateVO2 = new ObligateVO();
                BeanUtils.copyProperties(obligateVO1, obligateVO2);
                obligateVO2.setSapOutArea(realSapCode);
                obligateVO2.setSapInArea(regionAllotVO.getSapInArea());
                obligateVOList2.add(obligateVO2);
            }

            //生成入库单
            if(!warehouseInboundService.saveByRegionAllotIn(regionAllotAddVO, userId, orgId)) {
                throw new Exception("生成入库单时失败");
            }
            //生成出库单
            if (!warehouseDeliveryService.saveByRegionAllotOut(regionAllotAddVO, userId, orgId)) {
                throw new Exception("生成出库单时失败");
            }

//            boolean sapNoPostOrg = sapCommonService.sapNoPostOrg(orgId);
//            if(!sapNoPostOrg){
//                //同步到SAP创建预留单
//                ObligateHeaderVO headerVO = new ObligateHeaderVO();
//                headerVO.setBusinesId(regionAllotVO.getId());
//                headerVO.setBusinesOrder(regionAllotVO.getAllotOrder());
//                headerVO.setBusinesSingle(regionAllotVO.getAllotOrder().substring(0, 4));
//                sapCommonService.createObligateOrder(headerVO, obligateVOList1, obligateVOList2, orgId);
//            }
            return getResult(ErrorCode.Success, regionAllotDO.getAllotOrder());
        } else {
            throw new Exception("操作失败");
        }
    }



    /**
     * 添加区域调拨单（对外接口）
     *
     * @param regionAllotAddVO
     * @return
     * @throws Exception
     */
    @Transactional(rollbackFor = Exception.class)
    public ActionResult addRegionAllot4Tj(RegionAllotAddVO regionAllotAddVO) throws Exception {
        ActionResult<String> textResult = fastGenClient.textGuid();
        if (textResult.getCode() != ErrorCode.Success.getCode()) {
            return getResult(ErrorCode.IllegalArument, "获取GUID出错");
        }
        List<RegionAllotDetailVO> detailVOList = regionAllotAddVO.getDetailList();
        if (ListUtil.isNullOrEmpty(detailVOList)) {
            return getResult(ErrorCode.Failure, "缺少明细数据");
        }
        for (RegionAllotDetailVO detailVO : detailVOList) {
            if (detailVO.getAmount() == null || detailVO.getAmount().compareTo(BigDecimal.ZERO) == 0) {
                return getResult(ErrorCode.Failure, "数量不能为0");
            }
        }
        RegionAllotVO regionAllotVO = regionAllotAddVO.getHeaderInfo();
        CompanyInfoDO companyInfoDO = companyInfoMapper.itemBySap(regionAllotAddVO.getHeaderInfo().getSapCode());
        if (null == companyInfoDO) {
            return getResult(ErrorCode.Failure, "sapCode错误");
        }
        String orgId = companyInfoDO.getOrgId();
        String userId = regionAllotVO.getCreateId();
        regionAllotVO.setId(textResult.getValue());
        regionAllotVO.setAllotOrder(genDocumentService.genDocumentNo(BillDesc.RegionAllot, orgId));
        regionAllotVO.setOrgId(orgId);
        regionAllotVO.setInState(0);
        regionAllotVO.setOutState(0);
        regionAllotVO.setCreateDate(new Date());

        RegionAllotDO regionAllotDO = new RegionAllotDO();
        BeanUtils.copyProperties(regionAllotVO, regionAllotDO);

        String realSapCode = getRealSapCode(orgId);

        if (regionAllotMapper.insert(regionAllotDO) > 0) {
            //生成区域调拨详情记录
            List<ObligateVO> obligateVOList1 = new ArrayList<>();
            List<ObligateVO> obligateVOList2 = new ArrayList<>();
            ObligateVO obligateVO1;
            ObligateVO obligateVO2;
            for (RegionAllotDetailVO detailVO : detailVOList) {
                detailVO.setAllotOrder(regionAllotVO.getAllotOrder());
                detailVO.setOrgId(orgId);
                detailVO.setCreateId(regionAllotVO.getCreateId());
                detailVO.setCreateName(regionAllotVO.getCreateName());
                detailVO.setInAmount(BigDecimal.ZERO);
                detailVO.setInState(0);
                detailVO.setOutAmount(BigDecimal.ZERO);
                detailVO.setOutState(0);
                if (!regionAllotDetailService.add(detailVO)) {
                    throw new Exception("生成区域调拨详情记录失败");
                }

                //同步到SAP创建预留单
                obligateVO1 = new ObligateVO();
                obligateVO1.setMaterialNo(detailVO.getMaterialNo());
                obligateVO1.setAmount(detailVO.getAmount());
                obligateVO1.setMoveType(regionAllotVO.getMoveType());
                obligateVO1.setSapOutArea(regionAllotVO.getSapOutArea());
                obligateVO1.setSapInArea(realSapCode);
                obligateVOList1.add(obligateVO1);
                obligateVO2 = new ObligateVO();
                BeanUtils.copyProperties(obligateVO1, obligateVO2);
                obligateVO2.setSapOutArea(realSapCode);
                obligateVO2.setSapInArea(regionAllotVO.getSapInArea());
                obligateVOList2.add(obligateVO2);
            }

//            //生成入库单====================不生成入库单
//            if(!warehouseInboundService.saveByRegionAllotIn(regionAllotAddVO, userId, orgId)) {
//                throw new Exception("生成入库单时失败");
//            }
//            //生成出库单====================不生成入库单
//            if (!warehouseDeliveryService.saveByRegionAllotOut(regionAllotAddVO, userId, orgId)) {
//                throw new Exception("生成出库单时失败");
//            }

            //塔机的不创建预录单，所以下面先注释掉
//            //同步到SAP创建预留单
//            ObligateHeaderVO headerVO = new ObligateHeaderVO();
//            headerVO.setBusinesId(regionAllotVO.getId());
//            headerVO.setBusinesOrder(regionAllotVO.getAllotOrder());
//            headerVO.setBusinesSingle(regionAllotVO.getAllotOrder().substring(0, 4));
//            sapCommonService.createObligateOrder(headerVO, obligateVOList1, obligateVOList2, orgId);
            return getResult(ErrorCode.Success, regionAllotDO.getAllotOrder());
        } else {
            throw new Exception("操作失败");
        }
    }

    /**
     *获取公司下可过账的区域调拨单
     *
     * @param orgId
     * @param inOutCode 0：领入过账，1：领出过账
     * @return
     */
    public List<RegionAllotDO> list4SapPostingByOrg(String orgId, Integer inOutCode) {
        if (ObligateVO.OUT_SAP.equals(inOutCode)) {
            return regionAllotMapper.listOut4SapPosting(orgId);
        }
        return regionAllotMapper.listIn4SapPosting(orgId);
    }

    /**
     * 根据组织机构编码和仓库名称获取仓库信息
     * @param orgId
     * @param description
     * @return
     */
    public List<WarehouseDO> getWareHousesByOrgAndDescription(String orgId,String description){
        List<WarehouseDO> warehouseDOS = warehouseDOMapper.itemByDescription(orgId, description);
        if(CollectionUtils.isEmpty(warehouseDOS)){
            return Collections.EMPTY_LIST;
        }
        return warehouseDOS;
    }

    public List<RegionAllotDO> getRegionAllotByCrmOrder(String crmOrder){
        if(StringUtils.isEmpty(crmOrder)){
            return null;
        }
        List<RegionAllotDO> regionAllots = regionAllotMapper.findByCrmOrder(crmOrder);
        if(CollectionUtils.isEmpty(regionAllots)){
            return null;
        }
        return regionAllots;
    }

   /* public void testCrmInterface(String id,String orgId){
        RegionAllotAddVO allotAddVO = this.findByPK(id, "id", orgId);
        syncCrm(allotAddVO);
    }*/

   public List<RegionAllotDetailDO> getMaterialInfoByNo(List<String> billNoList){
       return regionAllotDetailMapper.getMaterialInfoByNo(billNoList);
   }

//   @Transactional(rollbackFor = Exception.class)
//   public ErrorCode syncCrm(String id,String orgId) {
//       RegionAllotAddVO regionAllotAddVO = findByPK(id, "id", orgId);
//       RegionAllotVO headerInfo = regionAllotAddVO.getHeaderInfo();
//       RegionAllotDO regionAllotDO = new RegionAllotDO();
//       BeanUtils.copyProperties(headerInfo, regionAllotDO);
//
//       Map resultMap = new HashMap();
//
//       RegionAllotDO updateDO = new RegionAllotDO();
//       updateDO.setId(regionAllotDO.getId());
//       List<RegionAllotDetailVO> detailList = regionAllotAddVO.getDetailList();
//       boolean isSuccess = true;
//
//       //同步入库状态和数量
//       for (RegionAllotDetailVO regionAllotDetailVO : detailList) {
//           resultMap = regionAllotDetailService.syncCrmByInbound(regionAllotDO.getAllotOrder(), regionAllotDetailVO.getMaterialNo(), regionAllotDO);
//           //同步失败需要回写
//           if (resultMap.get("Flag") != null && resultMap.get("Flag").equals(false)) {
//               String msg = updateDO.getSyncCrmMsg() == null ? "" : updateDO.getSyncCrmMsg();
//               msg += resultMap.get("Msg").toString() + ";";
//               updateDO.setSyncCrmFlag("2");
//               updateDO.setSyncCrmMsg(msg);
//               isSuccess = false;
//           }
//       }
//
//       //同步出库状态和数量
//       for (RegionAllotDetailVO regionAllotDetailVO : detailList) {
//           resultMap = regionAllotDetailService.syncCrmByOutbound(regionAllotDO.getAllotOrder(), regionAllotDetailVO.getMaterialNo(), regionAllotDO);
//           //同步失败需要回写
//           if (resultMap.get("Flag") != null && resultMap.get("Flag").equals(false)) {
//               String msg = updateDO.getSyncCrmMsg() == null ? "" : updateDO.getSyncCrmMsg();
//               msg += resultMap.get("Msg").toString() + ";";
//               updateDO.setSyncCrmFlag("2");
//               updateDO.setSyncCrmMsg(msg);
//               isSuccess = false;
//           }
//       }
//
//       //本次同步成功
//       if (isSuccess){
//           updateDO.setSyncCrmFlag("1");
//           updateDO.setSyncCrmMsg("操作成功");
//       }
//
//       regionAllotMapper.updateByPrimaryKeySelective(updateDO);
//
//       return ErrorCode.Success;
//   }
//    /**
//     * 调用顺丰OMS接口
//     * @return
//     */
//   private SfResponseDO sendToSf(RegionAllotAddVO allotAddVO) throws Exception {
//       XmlMapper xmlMapper = new XmlMapper();
//       xmlMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
//       xmlMapper.configure(SerializationFeature.WRAP_ROOT_VALUE, false);
//       xmlMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
//       xmlMapper.setPropertyNamingStrategy(PropertyNamingStrategy.UPPER_CAMEL_CASE);
//       xmlMapper.enable(MapperFeature.USE_STD_BEAN_NAMING);
//
//       SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//
//       PurchaseOrderServiceDO purchaseOrderServiceDO = new PurchaseOrderServiceDO();
//       purchaseOrderServiceDO.setService("PURCHASE_ORDER_SERVICE");
//       purchaseOrderServiceDO.setLang("zh-CN");
//
//       SfCheckDO sfCheckDO = new SfCheckDO();
//       sfCheckDO.setAccessCode(accessCode);
//       sfCheckDO.setCheckword(checkWord);
//       purchaseOrderServiceDO.setSfCheckDO(sfCheckDO);
//
//       PurchaseOrderRequestDO purchaseOrderRequestDO = new PurchaseOrderRequestDO();
//       purchaseOrderRequestDO.setCompanyCode(companyCode);
//
//       PurchaseOrderDO purchaseOrderDO = new PurchaseOrderDO();
//       purchaseOrderDO.setErpOrder(allotAddVO.getHeaderInfo().getAllotOrder());
//       purchaseOrderDO.setErpOrderType("1");//待定
//       purchaseOrderDO.setWarehouseCode(warehouseCode);
//       Calendar calendar = Calendar.getInstance();
//       calendar.setTime(new Date());
//       calendar.add(Calendar.DAY_OF_MONTH, 3);//当前时间加3天
//       purchaseOrderDO.setScheduledReceiptDate(simpleDateFormat.format(calendar.getTime()));
//       purchaseOrderDO.setVendorCode(vendorCode);
//
//
//       List<PurchaseOrderItemDO> itemDOList = new ArrayList<>();
//       for (RegionAllotDetailVO regionAllotDetailVO : allotAddVO.getDetailList()) {
//           PurchaseOrderItemDO itemDO = new PurchaseOrderItemDO();
//           itemDO.setSkuNo(regionAllotDetailVO.getMaterialNo());
//           itemDO.setQty(regionAllotDetailVO.getAmount());
//           itemDOList.add(itemDO);
//       }
//       purchaseOrderDO.setItemList(itemDOList);
//
//       List<PurchaseOrderDO> purchaseOrderDOS = new ArrayList<>();
//       purchaseOrderDOS.add(purchaseOrderDO);
//       purchaseOrderRequestDO.setPurchaseOrderDOList(purchaseOrderDOS);
//
//       SfRequestBodyDO sfRequestBodyDO = new SfRequestBodyDO();
//       sfRequestBodyDO.setPurchaseOrderRequestDO(purchaseOrderRequestDO);
//       purchaseOrderServiceDO.setSfRequestBodyDO(sfRequestBodyDO);
//
//       String xml = xmlMapper.writeValueAsString(purchaseOrderServiceDO);
//       String xmlWithSpecialCode = xml + specialCode;
//
//       //签名算法  base64(md5(xml+特殊字符串))
//       String dataDigest = new BASE64Encoder().encode(DigestUtils.md5DigestAsHex(xmlWithSpecialCode.getBytes()).getBytes());
//
//       MultiValueMap<String, String> map = new LinkedMultiValueMap<>();
//       map.add("logistics_interface", xml);
//       map.add("data_digest", dataDigest);
//       HttpHeaders headers = new HttpHeaders();
//       headers.add("Content-Type", "application/x-www-form-urlencoded");
//       HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<>(map, headers);
//
//       //调用顺丰 API
//       logger.info("调用顺丰入库接口，请求入参{}", xml);
//       ResponseEntity<String> stringResponseEntity = restTemplate.postForEntity(sfOmsApiUrl, request, String.class);
//       logger.info("调用顺丰入库接口，返回结果{}", stringResponseEntity.getBody());
//
//       return xmlMapper.readValue(stringResponseEntity.getBody(), SfResponseDO.class);
//   }

}
